codeforces 615 div3 MEX maximzing (构造 hash)

题目大意:

a=[] 即a是一个空的数列。a总共插入q次,每一次加入新元素y_i

 假如对于每次得到的新序列,我们都可以对其中的任一个元素做\pm x的操作,即:

vector<int> a;

for(int i=0;i<q;i++){
    a.push_back(yi);
    vector<int> tmp =a ;
    //ask sth about tmp 
    for(int j=0;j<(int)tmp.size();j++){
    tmp[j]+=ki * x;    //ki is not determined
    
    }
    
}

问我们每加入一个元素时候,通过对每个元素反复的加减x,这个序列中的最小的非负整数 最大是多少?

比如对于序列[0,1,1] 最小的非负整数是2,假如x=1,那么我们可以对第三个元素加1,最后形成序列[0,1,2],那么最小非负整数为3.

数据范围:y_i <= 1e9 , n,q,x<=1e5

解题思路:

首先,看到最小最大值问题,我们可以考虑2分,但是2分这里好像不好写,所以换一种思路,这里采取构造的方法来做。首先我们观察到,每次加入一个新的数字,其实我们可以对y_i=y_i mod \ x,这是等价的,通过以下公式推出:

y_i = y_i + kx 其中k为任意整数。

这时候,我们记录下每个数字y_i在序列中应该加几倍的x,比如第一次得到的y_i我们可以放在原来的位置,下一次假如还有y_i到来,我们把它放在y_i + x ,总结来讲:对于第m次出现的y_i,我们把它放在y_i + (m-1) * x 即可。通过这种构造我们可以尽可能地把数字在区间填满。然后在q次询问中,每次记录下最小的数字即可。最小的数字不可能超过q的范围即4e5。所以找最小的数字复杂度不会超。注意这里y_i范围到1e9,所以需要hash存储,对应c++的map.

#include <bits/stdc++.h>
#define int long long 
using namespace std;
int32_t main(){
    int q,x;cin>>q>>x;
    map<int,int> mm;
    set<int> ms;
    int mno=0;
    for(int i=0;i<q;i++){
        int t;cin>>t;
        t%=x;
        if(mm.count(t))mm[t]++;
        else mm[t]=0;
        ms.insert(t+mm[t]*x);
        if(t+mm[t]*x==mno){
            for(int no=mno;;no++){
                if(!ms.count(no)){
                    mno=no;
                    break;
                }
            }
        }
        cout<<mno<<endl;
    }
	return 0;
}
发布了171 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/FrostMonarch/article/details/104076124