标签:== ++ 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