标签:== ++ pos cond pre printf end span clu
题意:三种操作:区间置$0$,区间置$1$,区间取反,每次操作后输出MEX
直接离散化$l,r,r+1$,用线段树维护,pushdown的时候先处理覆盖标记再处理翻转标记
大套路?
#include<stdio.h>
#include<map>
using namespace std;
#define ll long long
struct ask{
int op;
ll l,r;
}q[100010];
map<ll,int>pos;
map<ll,int>::iterator it;
int sum[1200010],rst[1200010],rev[1200010];
ll rpos[300010];
void pushdown(int x,int ln,int rn){
if(rst[x]){
sum[x<<1]=ln*(rst[x]-1);
rst[x<<1]=rst[x];
sum[x<<1|1]=rn*(rst[x]-1);
rst[x<<1|1]=rst[x];
rst[x]=0;
rev[x<<1]=rev[x<<1|1]=0;
}
if(rev[x]){
sum[x<<1]=ln-sum[x<<1];
rev[x<<1]^=1;
sum[x<<1|1]=rn-sum[x<<1|1];
rev[x<<1|1]^=1;
rev[x]=0;
}
}
void pushup(int x){
sum[x]=sum[x<<1]+sum[x<<1|1];
}
void reset(int L,int R,int v,int l,int r,int x){
if(L<=l&&r<=R){
rst[x]=v+1;
sum[x]=v*(r-l+1);
rev[x]=0;
return;
}
int mid=(l+r)>>1;
pushdown(x,mid-l+1,r-mid);
if(L<=mid)reset(L,R,v,l,mid,x<<1);
if(mid<R)reset(L,R,v,mid+1,r,x<<1|1);
pushup(x);
}
void reverse(int L,int R,int l,int r,int x){
if(L<=l&&r<=R){
rev[x]^=1;
sum[x]=r-l+1-sum[x];
return;
}
int mid=(l+r)>>1;
pushdown(x,mid-l+1,r-mid);
if(L<=mid)reverse(L,R,l,mid,x<<1);
if(mid<R)reverse(L,R,mid+1,r,x<<1|1);
pushup(x);
}
ll query(int l,int r,int x){
if(l==r)return rpos[l];
int mid=(l+r)>>1;
pushdown(x,mid-l+1,r-mid);
if(sum[x<<1]<mid-l+1)return query(l,mid,x<<1);
return query(mid+1,r,x<<1|1);
}
int main(){
int n,m,i;
scanf("%d",&m);
pos[1]=1;
for(i=1;i<=m;i++){
scanf("%d%I64d%I64d",&q[i].op,&q[i].l,&q[i].r);
pos[q[i].l]=pos[q[i].r]=pos[q[i].r+1]=1;
}
for(n=1,it=pos.begin();it!=pos.end();n++,it++){
it->second=n;
rpos[n]=it->first;
}
for(i=1;i<=m;i++){
if(q[i].op==3)
reverse(pos[q[i].l],pos[q[i].r],1,n,1);
else
reset(pos[q[i].l],pos[q[i].r],2-q[i].op,1,n,1);
printf("%I64d\n",query(1,n,1));
}
}
标签:== ++ pos cond pre printf end span clu
原文地址:http://www.cnblogs.com/jefflyy/p/7953261.html