题意:现在有无穷多个位置(从 \(1\) 开始),一开始都是 \(0\),每次用 \(1/0\) 覆盖一个区间或翻转一个区间的 \(0/1\)。现在给出操作,求每次操作结束后第一个 \(0\) 的位置。
我们发现值域过大,不方便用数据结构维护,则考虑离散化。注意为了给可能存在的区间之间的空隙留下位置,例如 \([1,2]\) 和 \([4,5]\),离散化之后变成 \([1,2][3,4]\),\(3\) 的存在失去了。则将 \(l\pm 1\) 和 \(r\pm 1\) 一起离散化进去,但是注意如果 \(r-1\) 和 \(l-1\) 是 \(0\),不能加入。
然后考虑用线段树维护。我们在线段树上维护 \(sum,len,tg\),分别表示当前区间的 \(1\) 的总和、当前区间的总长度、当前区间面临的操作种类。
操作的过程,就是给区间打标记。
考虑如何打上或下传标记。
假设当前节点的标记种类是 \(tg\),新加入 \(d\),如果 \(tg=0\),直接用 \(d\) 覆盖。如果 \(d=1\) 或 \(2\),也直接用 \(d\) 覆盖。如果 \(d\) 是 \(3\),更改为 \(3-d\)。这样,原来的 \(1\) 和 \(2\) 交换,原来是 \(3\) 则相当于没做。
然后考虑处理标记。若 \(tg=1\),令 \(sum=len\)。若 \(tg=2\),令 \(sum=0\)。若 \(tg=3\),令 \(sum=len-sum\)。
最后考虑如何查询,我们从根节点开始递归,先递归左节点,如果左边满了(\(len=sum\)),就去右边,直到找到答案。因为我们离散化的时候离散化了 \(r_{max}+1\),所以一定会找到答案的。
还有一个问题,就是我们查询之后要上传答案。如果我们在左子树找到答案就返回,是不能正确得到答案的。正确的做法是即使左子树有答案了,也在右儿子 \(push\) 一下 \(tg\),从而正确的合并答案。
int n,t[100005];
ll l[100005],r[100005],v[600005],m;
struct node{
int l,r,sum,tg,len;
}sg[2400005];
inline void init(int i,int l,int r){
sg[i].l=l,sg[i].r=r,sg[i].tg=0,sg[i].sum=0,sg[i].len=(sg[i].r-sg[i].l+1);
if(l==r)return;
init(i<<1,l,l+r>>1);
init(i<<1|1,(l+r>>1)+1,r);
}
inline void addtg(int i,int d){
if(!sg[i].tg||d<=2)sg[i].tg=d;
else sg[i].tg=3-sg[i].tg;
}
inline void psh(int i){
if(!sg[i].tg)return;
if(sg[i].tg==1)sg[i].sum=sg[i].len;
else if(sg[i].tg==2)sg[i].sum=0;
else sg[i].sum=sg[i].len-sg[i].sum;
if(sg[i].l!=sg[i].r){
addtg(i<<1,sg[i].tg);
addtg(i<<1|1,sg[i].tg);
}sg[i].tg=0;
}
inline void add(int i,int d,int l,int r){
psh(i);
if(sg[i].l>r||sg[i].r<l)return;
if(sg[i].l>=l&&sg[i].r<=r){
addtg(i,d);
psh(i);
return;
}
add(i<<1,d,l,r);
add(i<<1|1,d,l,r);
sg[i].sum=sg[i<<1].sum+sg[i<<1|1].sum;
}
inline int qry(int i,bool p){
psh(i);
if(sg[i].sum==sg[i].len||p)return -1;
if(sg[i].l==sg[i].r)return sg[i].l;
int res=qry(i<<1,0);
if(res==-1)res=qry(i<<1|1,0);
else qry(i<<1|1,1);
sg[i].sum=sg[i<<1].sum+sg[i<<1|1].sum;
return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
v[++m]=1;
rp(i,n){
cin>>t[i]>>l[i]>>r[i];
if(l[i]!=1)v[++m]=l[i]-1;
v[++m]=l[i],v[++m]=l[i]+1;
v[++m]=r[i],v[++m]=r[i]+1;
if(r[i]!=1)v[++m]=r[i]-1;
}
sort(v+1,v+1+m);
m=unique(v+1,v+1+m)-v-1;
init(1,1,m);
rp(i,n){
l[i]=lower_bound(v+1,v+1+m,l[i])-v;
r[i]=lower_bound(v+1,v+1+m,r[i])-v;
}
rp(i,n){
add(1,t[i],l[i],r[i]);
cout<<v[qry(1,0)]<<'\n';
}
return 0;
}
//Crayan_r
标签:++,sum,Queries,len,int,CF817F,tg,sg,MEX
From: https://www.cnblogs.com/jucason-xu/p/17152281.html