CF817F MEX Queries

题面翻译

  • 维护一个集合,初始为空。
  • \(3\) 种操作:
    1. \([l,r]\) 中在集合中没有出现过的数添加到集合中。
    2. \([l,r]\) 中在集合中出现过的数从集合中删掉。
    3. \([l,r]\) 中在集合中没有出现过的数添加到集合中,并把 \([l,r]\) 中在集合中出现过的数从集合中删掉。
  • 每次操作后输出集合的 \(\operatorname{MEX}\) —— 在集合中没有出现过的最小正整数。
  • \(1\le n\le 10^5\)\(1\le l\le r\le 10^{18}\)

样例 #1

样例输入 #1

3
1 3 4
3 1 6
2 1 3

样例输出 #1

1
3
1

样例 #2

样例输入 #2

4
1 1 3
3 5 6
2 4 4
3 1 6

样例输出 #2

4
4
4
1

分析

询问可以抽象成为区间用 \(0,1\) 覆盖,区间翻转,在每次操作后输出第一个 \(0\) 的下标。

首先这些玩意都可以线段树进行维护,但序列长度过大,询问次数正常,所以动态开点。

需要存储区间和,区间赋值标记和区间修改标记。

注意 pushdown 时的标记下传顺序。

注意到当节点被打上赋值 tag 时,其子节点已经无用,可以删除,使用垃圾回收可以减小常数。(卡常要用)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll t[100005*100],l,r;
int ls[100005*100],rs[100005*100],rt,n,tot,maxx=-1,opt;
int pl[100005*100],plt;
bool rev[100005*100];
char tag[100005*100];
inline int New(){return plt?pl[plt--]:++tot;}
void pushup(int num){t[num]=t[ls[num]]+t[rs[num]];}
void pushdown(int num,ll l,ll r){
    ll mid=l+r>>1;
    if(tag[num]^'-'){
        if(!ls[num])ls[num]=New();
        if(!rs[num])rs[num]=New();
        tag[ls[num]]=tag[rs[num]]=tag[num];
        rev[ls[num]]=rev[rs[num]]=0;
        if(tag[num]=='1')t[ls[num]]=mid-l+1,t[rs[num]]=r-mid;
        else t[ls[num]]=t[rs[num]]=0;
        tag[num]='-';
    }
    if(rev[num]){
        if(!ls[num])ls[num]=New();
        if(!rs[num])rs[num]=New();
        if(tag[ls[num]]^'-')tag[ls[num]]=(tag[ls[num]]=='0'?'1':'0');
        else rev[ls[num]]^=1;
        if(tag[rs[num]]^'-')tag[rs[num]]=(tag[rs[num]]=='0'?'1':'0');
        else rev[rs[num]]^=1;
        rev[num]=0;
        t[ls[num]]=mid-l+1-t[ls[num]],t[rs[num]]=r-mid-t[rs[num]];
    }
}
void dfs(int p){
	if(!p)return;
	if(plt<=7e6)pl[++plt]=p;
	dfs(ls[p]),dfs(rs[p]);
	t[p]=ls[p]=rs[p]=rev[p]=0,tag[p]='-';
}
void update(int &num,ll l,ll r,ll x,ll y,int k){
    if(x>r||y<l)return;
    if(!num)num=New();
    if(x<=l&&r<=y){
        if(k==1)tag[num]='1',t[num]=r-l+1,rev[num]=0;
        else if(k==2)tag[num]='0',t[num]=rev[num]=0;
        else if(k==3){
            if(tag[num]^'-')tag[num]=(tag[num]=='0'?'1':'0');
            else rev[num]^=1;
            t[num]=r-l+1-t[num];
        }
        if(k<=2)dfs(ls[num]),dfs(rs[num]),ls[num]=rs[num]=0;	
        return;
    }
    pushdown(num,l,r);
    ll mid=l+r>>1;
    update(ls[num],l,mid,x,y,k),update(rs[num],mid+1,r,x,y,k);
    pushup(num);
}
ll query(int &num,ll l,ll r){
    if(!num||l==r)return l;
    pushdown(num,l,r);
    ll mid=l+r>>1;
    if(t[ls[num]]<mid-l+1)return query(ls[num],l,mid);
    return query(rs[num],mid+1,r);
}
signed main(){
    scanf("%d",&n);for(int i=0;i<1e7;i++)tag[i]='-';
    for(int i=1;i<=n;i++){
        scanf("%d%lld%lld",&opt,&l,&r);
        update(rt,1ll,(ll)(1e18)+1ll,l,r,opt);
        printf("%lld\n",query(rt,1ll,(ll)(1e18)+1ll));
    }
    return 0;
}
posted @ 2023-06-24 11:43  alex_liu09  阅读(31)  评论(0)    收藏  举报