第十五屆中北大學算法與程序設計競賽 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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章