CF817F MEX Queries(线段树上二分)
题意
维护一个01串,一开始全部都是0
3种操作
1.把一个区间都变为1
2.把一个区间都变为0
3.把一个区间的所有数字翻转过来
每次操作完成之后询问区间最小的0的位置
l,r<=10^18
题解
区间操作想到线段树,离散化不用说,l,r太大了。
1,2,3操作非常好维护。
然后在查询中二分查询就好了。
一开始看别的博客说要加1节点和r+1节点不知道为什么。
因为我的查询想的是,查询前面全都是1的区间的长度。后来发现做不了。就乖乖照题解做了。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<algorithm> 6 #include<map> 7 using namespace std; 8 const long long N=150020; 9 map<long long,long long> mp; 10 long long b[N*4],n,m,cnt; 11 struct ask{ 12 long long l,r; 13 long long k; 14 }q[N]; 15 struct tree{ 16 long long l,r,sum,sev,lazy; 17 }tr[N*40]; 18 void build(long long l,long long r,long long now){ 19 tr[now].l=l; 20 tr[now].r=r; 21 tr[now].lazy=-1; 22 if(l==r)return; 23 long long mid=(l+r)>>1; 24 build(l,mid,now*2); 25 build(mid+1,r,now*2+1); 26 } 27 void pushdown(long long now){ 28 long long mid=(tr[now].l+tr[now].r)>>1; 29 if(tr[now].lazy!=-1){ 30 tr[now*2].lazy=tr[now*2+1].lazy=tr[now].lazy; 31 tr[now*2].sum=(mid-tr[now].l+1)*tr[now].lazy; 32 tr[now*2+1].sum=(tr[now].r-mid)*tr[now].lazy; 33 tr[now*2].sev=tr[now*2+1].sev=0; 34 tr[now].lazy=-1; 35 } 36 if(tr[now].sev){ 37 tr[now*2].sev^=1; 38 tr[now*2+1].sev^=1; 39 tr[now*2].sum=(mid-tr[now].l+1)-tr[now*2].sum; 40 tr[now*2+1].sum=(tr[now].r-mid)-tr[now*2+1].sum; 41 tr[now].sev=0; 42 } 43 } 44 void update(long long l,long long r,long long now,long long k){ 45 // cout<<l<<" "<<r<<" "<<tr[now].l<<" "<<tr[now].r<<" "<<now<<endl; 46 pushdown(now); 47 if(tr[now].l==l&&tr[now].r==r){ 48 tr[now].sum=(tr[now].r-tr[now].l+1)*k; 49 tr[now].lazy=k; 50 tr[now].sev=0; 51 return ; 52 } 53 long long mid=(tr[now].l+tr[now].r)>>1; 54 if(l>mid){ 55 update(l,r,now*2+1,k); 56 } 57 else if(r<=mid){ 58 update(l,r,now*2,k); 59 } 60 else{ 61 update(l,mid,now*2,k); 62 update(mid+1,r,now*2+1,k); 63 } 64 tr[now].sum=tr[now*2].sum+tr[now*2+1].sum; 65 } 66 void serve(long long l,long long r,long long now){ 67 pushdown(now); 68 if(tr[now].l==l&&tr[now].r==r){ 69 tr[now].sum=(tr[now].r-tr[now].l+1)-tr[now].sum; 70 tr[now].sev^=1; 71 return; 72 } 73 long long mid=(tr[now].l+tr[now].r)>>1; 74 if(l>mid)serve(l,r,now*2+1); 75 else if(r<=mid)serve(l,r,now*2); 76 else{ 77 serve(l,mid,now*2); 78 serve(mid+1,r,now*2+1); 79 } 80 tr[now].sum=tr[now*2].sum+tr[now*2+1].sum; 81 } 82 void check(long long now){ 83 if(tr[now].l==tr[now].r){ 84 printf("%lld\n",b[tr[now].l]); 85 return ; 86 } 87 long long mid=(tr[now].l+tr[now].r)>>1; 88 pushdown(now); 89 if(tr[now*2].sum<mid-tr[now].l+1)check(now*2); 90 else return check(now*2+1); 91 } 92 int main(){ 93 scanf("%lld",&m); 94 for(long long i=1;i<=m;i++){ 95 scanf("%lld%lld%lld",&q[i].k,&q[i].l,&q[i].r); 96 q[i].r++; 97 b[++cnt]=q[i].l; 98 b[++cnt]=q[i].r; 99 } 100 b[++cnt]=1; 101 sort(b+1,b+1+cnt); 102 n=unique(b+1,b+1+cnt)-(b+1); 103 for(long long i=1;i<=n;i++){ 104 mp[b[i]]=i; 105 } 106 build(1,n,1); 107 for(long long i=1;i<=m;i++){ 108 if(q[i].k==1){ 109 update(mp[q[i].l],mp[q[i].r]-1,1,1); 110 } 111 else if(q[i].k==2){ 112 update(mp[q[i].l],mp[q[i].r]-1,1,0); 113 } 114 else{ 115 serve(mp[q[i].l],mp[q[i].r]-1,1); 116 } 117 check(1); 118 } 119 return 0; 120 }