CF817F MEX Queries
题面翻译
- 维护一个集合,初始为空。
- 有 \(3\) 种操作:
- 把 \([l,r]\) 中在集合中没有出现过的数添加到集合中。
- 把 \([l,r]\) 中在集合中出现过的数从集合中删掉。
- 把 \([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;
}

浙公网安备 33010602011771号