牛客 集合操作(stl)

对于这题,可以考虑离散化后用树状数组维护+-并且维护两点之间的个数,之后二分求取第一个离散化后两点之前的个数不等于离散化前的个数。

这说明中间有些没在集合里面。这样就能获得答案。

如果答案等于查询点,说明当前点就不在集合,不然的话,就是查询点+1。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
struct node{
    int id,x;
}q[N];
int tr[N];
int st[N];
int lowbit(int x){
    return x&-x;
}
void add(int x,int c){
    int i;
    for(i=x;i<=N;i+=lowbit(i)){
        tr[i]+=c;
    }
}
int sum(int x){
    int res=0;
    int i;
    for(i=x;i;i-=lowbit(i)){
        res+=tr[i];
    }
    return res;
}
int main(){
    int n;
    cin>>n;
    int i;
    vector<int> num;
    for(i=1;i<=n;i++){
        scanf("%d%d",&q[i].id,&q[i].x);
        num.push_back(q[i].x);
        //num.push_back(q[i].x+1);
    }
    sort(num.begin(),num.end());
    num.erase(unique(num.begin(),num.end()),num.end());
    for(i=1;i<=n;i++){
        int a=q[i].id,b=q[i].x;
        int pos=lower_bound(num.begin(),num.end(),b)-num.begin()+1;
        if(a==1){
            if(!st[pos]){
               add(pos,1);
               st[pos]=1;
            }
        }
        else if(a==2){
            if(st[pos]){
                add(pos,-1);
                st[pos]=0;
            }
        }
        else{
            int base=sum(pos-1);
            int l=pos,r=(int)num.size()+1;
            while(l<r){
                int mid=l+r>>1;
                int val=sum(mid)-base;
                if(val==num[mid-1]-num[pos-1]+1) //找到第一个不是连续的点
                    l=mid+1;
                else
                    r=mid;
            }
            if(l==pos){
                cout<<num[l-1]<<endl;
            }
            else{
                cout<<num[l-2]+1<<endl;
            }
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12984776.html