ICPC区域赛热身赛第一场补题

昨天打了一场热身赛,签到题还是有的,但是难题居多,今天把几道题的题解写一下


第一题 前缀表

这道题目其实题意挺简单的,可以理解成是插板子,只要能想到使用前缀表这个知识点,问题就迎刃而解了。

题干

牛客网 F

To save money, Santa Claus has started hiring other animals besides reindeer to pull his sleigh via short term ‘gig’ contracts. As a result, the actual animals that show up to pull his sleigh for any given trip can vary greatly in size. Last week he had 2 buffalo, 37 voles and a schnauzer. Unfortunately, both buffalo were hitched on the left side and the entire sleigh flipped over in mid-flight due to the weight imbalance.To prevent such accidents in the future, Santa needs to divide the animals for a given trip into two groups such that the sum of the weights of all animals in one group equals the sum of the weights of all animals in the other. To make the hitching process efficient, Santa is seeking an integer target weight t such that all animals that are lighter than t go in one group and those heavier than t go into the other. If there are multiple such t, he wants the smallest one. There’s one small wrinkle: what should be done if there some animals have weight exactly equal to t? Santa solves the problem this way: if there are an even number of such animals, he divides them equally among the two
groups (thus distributing the weight evenly). But if there are an odd number of such animals, then one of those animals is sent to work with the elves to make toys (it is not put in either group), and the remaining (now an even number)are divided evenly among the two groups.
输入描述:
Input describes a list of animals’ weights. The first line contains an integer
m (2≤m≤1052≤m≤105), indicating the number of animals. The next m lines each have a positive integer. These are the weights of the animals (in ounces). Animals weighing more than 20000
20000 ounces are too big to pull the sleigh so no given weight will exceed this maximum.
输出描述:
Output the smallest integer target weight t, as described above. It’s
guaranteed that it is possible to find such an integer.

输入样例

4
3
6
1
2

输出样例

4

输入样例

4
11
8
3
10

输出样例

10

思路解释

题干解释:给你若干个数据,需要找到最小的数据t,使得比t小的数据归位一类,大于t的数据归为一类,且两类内数据相加总和大小相同。(如果出现t就是其中一个数据的话,则进行以下处理,如果t是奇数,则将t-1,将剩下的平分;偶数的话直接平分)

思路:这道题的特判分析一下,你会发现其实对结果没有任何影响,因为不管哪种情况,t重量的动物都会被平分,因此只需要使得两边相同就可以了,这里我们就用到了前缀表这个知识点,将前i个数据的sum和累加存储在a[i]中,每次增加一个数据就是本身。

前缀表做好以后,我们就可以直接暴力寻找左边等于右边的t了(题目说了,给的数据是一定可行的,所以放下找就行了)

容易爆WA的原因就是特判可能忽略了(代码里有说)


AC代码

#include<bits/stdc++.h>
using namespace std;
 
int a[20001];
long long s[100001];
int main()
{
    
    
    int m;
 
    while(~scanf("%d",&m))
    {
    
    
        memset(a,0,sizeof(a));
        memset(s,0,sizeof(s));
        int z;
        int mx=0;
        while(m--)
        {
    
    
            scanf("%d",&z);
            ++a[z];
            mx=max(mx,z);
        }
        //前缀表的建立
        for(int i=1;i<=mx;++i)
        {
    
    
            if(i==1)s[i]=i*a[i];
            else s[i]=s[i-1]+i*a[i];
        }
        int t;
        //注意有个特判,如果mx=1的话需要直接输出1
        if(mx==1)
        {
    
    
            printf("1\n");
        }
        else
        {
    
    
        for(int i=2;i<=mx;++i)
        {
    
    
            if(s[i-1]==(s[mx]-s[i]))
            {
    
    
                t=i;
                break;
            }
        }
        printf("%d\n",t);
        }
    }
    return 0;
}

第二题 bfs最短路

这道题其实拔掉马甲,其实就是普通的迷宫bfs类型最短路,就是那种多种路径找到迷宫出口求最短的路径(和有不同权值的题目不是一个类型,这种相当于权值相同都是1)


题干

牛客 H

样例图

Alice and Bob are playing a game on a simple connected graph with N nodes and M edges.

Alice colors each edge in the graph red or blue.

A path is a sequence of edges where each pair of consecutive edges have a node in common. If the first edge in the pair is of a different color than the second edge, then that is a ‘‘color change.’’

After Alice colors the graph, Bob chooses a path that begins at node 1 and ends at node N. He can choose any path on the graph, but he wants to minimize the number of color changes in the path. Alice wants to choose an edge coloring to maximize the number of color changes Bob must make. What is the maximum number of color changes she can force Bob to make, regardless of which path he chooses? changes she can force Bob to make, regardless of which path he chooses?


思路解释

这道题其实就是寻找从1到n的最短路径,最少的涂色方案其实就是路径-1,那么我们直接套用最短路径bfs的板子就可以了,开整!

具体解释:bfs的最短路实现其实就是从起始点出发,遍历能走且没走过的路,然后将它们按顺序存储到vis记录累加起来,最后最先走到终点的就是最短路径,具体可以查看我之前的博文有详细的解释


AC代码

#include<string>
#include<iomanip>
#include<iostream>
#include<set>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<algorithm>
#include<queue>
#include<vector>
#define m(x) memset(x,0,sizof x);
using namespace std;
const int maxn = 1e5+10;
int n,m;
int vis[maxn]={
    
    0};
vector<int>mp[maxn];

void bfs()
{
    
    
    queue<int>q;
    vis[1] = 0;
    q.push(1);
    while(!q.empty())
    {
    
    
        
        int top = q.front();
        if(top==n)return;
        q.pop();
        for(int i=0;i<mp[top].size();i++){
    
    
            if(vis[mp[top][i]]==0){
    
    
                vis[mp[top][i]] = vis[top] + 1;
                q.push(mp[top][i]);
            }
        }
    }
}
int main(){
    
    
    
    int x,y;
    scanf("%d%d",&n,&m);
    while(m--){
    
    
        cin >> x >> y;
        mp[x].push_back(y);
        mp[y].push_back(x);
    }
    bfs();
    printf("%d\n",vis[n]-1);
    
    
    return 0;
}




第三题 构造子序列+堆栈操作

这道题比赛的时候没有打出来(做题策略的原因,队友先去肝B题了,这道题其实原理和代码不难,熟悉堆栈操作就可以解决)

题干

牛客 E

You are given a list of integers x1,x2,······,xn, and a number k. It is guaranteed that each i from 1 to k appears in the list at least once. Find the lexicographically smallest subsequence of x that contains each integer from 1 to k exactly once. The first line will contain two integers n and k, with 1≤k≤n≤200000.
The following n lines will each contain an integer xi,1≤xi≤k.
输出描述:
Write out on one line, separated by spaces, the lexicographically smallest subsequence of x that has each integer from 1 to k exactly once.

示例1
输入

6 3
3
2
1
3
1
3

输出

2 1 3

示例2
输入

10 5
5
4
3
2
1
4
1
1
5
5

输出

3 2 1 4 5

思路解释

这道题题意是寻找最小字典序的子序列,而且子序列中每个数据有且只能出现一次(从1到k,连续)

那么我们可以总结出来的策略如下:
我们先建立一个集合,如果取出尾部b与便利的ai相比较,如果同时满足以下条件
1.ai<b
2.后面还有出现b
则将b从集合中删除,这样留下来的就是最佳答案。

这个策略实际上就是FILO(first in last out),我们采用堆栈可以轻松实现


AC代码

#include<string>
#include<iomanip>
#include<iostream>
#include<set>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#define m(x) memset(x,0,sizof x);
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn = 1e5+10;
int a[200007],cnt[200007],vis[200007];
stack<int>s;
int main(){
    
    
    
    int n,k;
    cin >> n >> k;
    rep(i,1,n){
    
    cin >> a[i];cnt[a[i]]++;}
    rep(i,1,n){
    
    
        cnt[a[i]]--;
        if(vis[a[i]])continue;
        while(s.size()&&s.top()>a[i]&&cnt[s.top()]){
    
    
            int t = s.top();
            s.pop();
            vis[t] = 0;
        }
        s.push(a[i]);
        vis[a[i]] = 1;
    }
    stack<int>ans;
    while(s.size()){
    
    ans.push(s.top());s.pop();}
    while(ans.size()){
    
    
        cout << ans.top() << " ";
        ans.pop();
    }
    return 0;
}

总结

接下来一个月还需要加强对各个模版的训练巩固

猜你喜欢

转载自blog.csdn.net/DAVID3A/article/details/114530209