1. 程式人生 > >CF817F MEX Queries(線段樹上二分)

CF817F MEX Queries(線段樹上二分)

ret 技術分享 tree else 線段 std con b+ play

題意

維護一個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 }
View Code

CF817F MEX Queries(線段樹上二分)