第十五届中北大学算法与程序设计竞赛 F:集合操作(set+思维)

如果,我们有个答案数组存了所有的数,当1操作其实是在这个数组中删去x,而2操作是加上x,而3操作的话就是二分找到第一个大于等于x的数。
但x<1000000000,直接存所有数是不可能的。而想一下,每个x,如果它不在题目的S集合中,那么答案肯定就是x,否则就得看前面有没有往S中添加过x+1。

而添加过x+1的话,就还得看x+2,一直到一个没有操作中出现过的数,而这个数肯定是操作出现过的某个数+1。

所有对于每次操作,我们把x跟x+1添加进我们前面所说的答案数组中,这个数组的也就2*n而已了。

为了方便直接用set来实现这个答案数组即可。因为set操作大概是log的,所以nlogn时间复杂度上也可以。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
vector<pai>op;
set<int>sp;
 
int main() {
    #ifndef ONLINE_JUDGE
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt","w",stdout);
    #endif
    int n;
    cin >>n;
    for(int i = 1;i <= n;++i){
        int op1,va;
        scanf("%d%d",&op1,&va);
        op.pb({op1,va});
        sp.insert(va);
        sp.insert(va+1);
    }  
    for(int i = 0;i < op.size();++i){
        if(op[i].fi==1){
            sp.erase(op[i].se);
        }else if(op[i].fi==2){
            sp.insert(op[i].se);
        }else{
            int ans = *sp.lower_bound(op[i].se);
            printf("%d\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/106338715
今日推荐