标签:www 节点 nbsp 离线 void efi stream || open
给你一个无限长的数组,初始的时候都为0,有3种操作:
操作1是把给定区间[l,r][l,r] 设为1,
操作2是把给定区间[l,r][l,r] 设为0,
操作3把给定区间[l,r][l,r] 0,1反转。
l,r<=1018
一共n(n<=105)个操作,每次操作后要输出最小位置的0。
看到维护区间,想到线段树。
看到数据范围,想到把操作离线然后离散化。
然后再yy一下合并状态:
每个节点维护两个信息:
min0表示该区间最小位置的0,初始值为l (当时错在了这里)。
min1表示该区间最小位置的1,初始值为inf。
合并时左右取最小即可
通过懒标记维护。
#include<algorithm> #include<iostream> #include<cstdio> #include<map> using namespace std; #define N 5000000 #define int long long #define root 1,1,maxn #define mid (l+r)/2 #define ls id*2 #define rs id*2+1 #define lc ls,l,mid,tl,tr #define rc rs,mid+1,r,tl,tr #define inf 4611686018427387904 int min0[N],min1[N],dic[N],tag[N],maxn,neg[N]; struct opt { int type,l,r; }opts[N]; map<int,int> m; void pushdown(int id,int l,int r) { if(tag[id]) { tag[ls]=tag[rs]=tag[id]; neg[ls]=neg[rs]=0; if(tag[id]-1>0) min0[ls]=min0[rs]=inf,min1[ls]=l,min1[rs]=mid+1; else min0[ls]=l,min0[rs]=mid+1,min1[ls]=min1[rs]=inf; } if(neg[id]) { //if(tag[ls]||tag[rs]) throw ‘a‘; neg[ls]=!neg[ls],neg[rs]=!neg[rs]; swap(min0[ls],min1[ls]); swap(min0[rs],min1[rs]); } neg[id]=tag[id]=0; } void update(int id) { min0[id]=min(min0[ls],min0[rs]); min1[id]=min(min1[ls],min1[rs]); } void set(int id,int l,int r,int tl,int tr,int v) { if(l>=tl&&r<=tr) { if(v) min0[id]=inf,min1[id]=l; else min0[id]=l,min1[id]=inf; tag[id]=v+1; neg[id]=0; return; } pushdown(id,l,r); if(tl<=mid) set(lc,v); if(tr>mid) set(rc,v); update(id); } void set2(int id,int l,int r,int tl,int tr) { if(l>=tl&&r<=tr) { swap(min0[id],min1[id]); neg[id]=!neg[id]; return; } pushdown(id,l,r); if(tl<=mid) set2(lc); if(tr>mid) set2(rc); update(id); } void build(int id,int l,int r) { min0[id]=l; min1[id]=inf; if(l==r) return; build(ls,l,mid); build(rs,mid+1,r); } signed main() { int n,cnt=0; //freopen("data.in","r",stdin); //freopen("my.out","w",stdout); cin>>n; for(int i=1;i<=n;i++) { scanf("%lld%lld%lld",&opts[i].type,&opts[i].l,&opts[i].r); if(!opts[i].l||!opts[i].r) throw "a"; m[opts[i].l]=1; m[opts[i].r]=1; m[opts[i].r+1]=1; } m[1]=1; for(map<int,int>::iterator it=m.begin();it!=m.end();it++)//通过map离散化 { dic[++cnt]=(*it).first; (*it).second=cnt; } maxn=m.size(); build(root); for(int i=1;i<=n;i++) { if(opts[i].type<=2) set(root,m[opts[i].l],m[opts[i].r],opts[i].type==1); else set2(root,m[opts[i].l],m[opts[i].r]); printf("%lld\n",dic[min0[1]]); } }
Codeforces - 817F. MEX Queries
标签:www 节点 nbsp 离线 void efi stream || open
原文地址:https://www.cnblogs.com/linzhuohang/p/11330755.html