1. 程式人生 > >bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572

bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572

1的個數 return 為什麽 truct urn OS bsp print -s

記一下:線段樹占空間是$2^{ceil(log2(n))+1}$

這個就是一個線段樹區間操作題,各種標記的設置、轉移都很明確,只要熟悉這類題應該說是沒有什麽難度的。

由於對某區間set之後該區間原先待進行的取反操作失效(被覆蓋),因此規定tag同時存在時set的標記先進行操作,這樣對區間加上set標記時要去掉原有的取反標記。

對於操作4,線段樹上每個區間維護6個值,分別表示:該區間最多的連續0/1,從左側數起/從右側數起/其中任意位置。題目中不問連續0,為什麽連續0也要維護呢?這是為了在進行取反操作時,O(1)完成標記的維護(直接交換對0、1維護的3個值就行了)。

對於操作3,線段樹上每個區間維護該區間1的個數。此時不需要額外記錄0的個數,0的個數可以由區間總數-1的個數得到。

規定:set的標記為-1時表示不需要set操作,為0/1時表示需要set為該標記的值。

註意一點:對於取反的tag,每次取反操作的時候都是將tag取反,而不是置為1,不然在同一個位置取反兩次就不對了。

各個標記含義同普通線段樹:當前節點已經操作,其所有(任意級的)子節點待操作。維護的時候轉移都是遞推,細的就不講了,有點多,要細心比對。

然而...

感覺自己藥丸啊...調了三個小時才調出來,各種各樣詭異的錯誤...如果省選考這個肯定沒法做了..

幸好這個樣例夠強。。有一些奇怪的錯誤通過樣例就查出來了,過了樣例就1A了,不然真的不知道要調到什麽時候。。。

note:以下程序中打了註釋的語句都是錯過的。。。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define mid ((l+r)>>1)
  5 #define lc (num<<1)
  6 #define rc (num<<1|1)
  7 using namespace std;
  8 struct Th
  9 {
 10     int a,b,c;
 11     bool d;//是否全部是1
 12     int len;
13 Th(int aa=0,int bb=0,int cc=0,bool dd=1,int ll=0):a(aa),b(bb),c(cc),d(dd),len(ll){} 14 }; 15 int num1[270000],maxnum[270000][2][3],settag[270000]; 16 bool revtag[270000]; 17 int n,m; 18 //定義tag同時存在時settag先進行操作 19 int a[100010]; 20 int L,R,x; 21 //maxnum[][0/1][0/1/2]表示最多的連續0/1,接左側/接右側/中間 22 void pd(int l,int r,int num) 23 { 24 if(settag[num]!=-1) 25 { 26 num1[lc]=settag[num]*(mid-l+1); 27 maxnum[lc][0][0]=maxnum[lc][0][1]=maxnum[lc][0][2]=(1-settag[num])*(mid-l+1); 28 maxnum[lc][1][0]=maxnum[lc][1][1]=maxnum[lc][1][2]=settag[num]*(mid-l+1); 29 num1[rc]=settag[num]*(r-mid); 30 maxnum[rc][0][0]=maxnum[rc][0][1]=maxnum[rc][0][2]=(1-settag[num])*(r-mid); 31 maxnum[rc][1][0]=maxnum[rc][1][1]=maxnum[rc][1][2]=settag[num]*(r-mid); 32 revtag[lc]=revtag[rc]=0; 33 settag[lc]=settag[rc]=settag[num]; 34 settag[num]=-1; 35 } 36 if(revtag[num]) 37 { 38 num1[lc]=mid-l+1-num1[lc]; 39 num1[rc]=r-mid-num1[rc]; 40 swap(maxnum[lc][0][0],maxnum[lc][1][0]); 41 swap(maxnum[lc][0][1],maxnum[lc][1][1]); 42 swap(maxnum[lc][0][2],maxnum[lc][1][2]); 43 swap(maxnum[rc][0][0],maxnum[rc][1][0]); 44 swap(maxnum[rc][0][1],maxnum[rc][1][1]); 45 swap(maxnum[rc][0][2],maxnum[rc][1][2]); 46 revtag[lc]^=1;revtag[rc]^=1; 47 revtag[num]=0; 48 } 49 } 50 void update(int l,int r,int num) 51 { 52 num1[num]=num1[lc]+num1[rc]; 53 maxnum[num][0][0]=maxnum[lc][0][0]; 54 if(num1[lc]==0) maxnum[num][0][0]=(mid-l+1)+maxnum[rc][0][0]; 55 maxnum[num][0][1]=maxnum[rc][0][1]; 56 if(num1[rc]==0) maxnum[num][0][1]=(r-mid)+maxnum[lc][0][1]; 57 maxnum[num][1][0]=maxnum[lc][1][0]; 58 if(num1[lc]==mid-l+1) maxnum[num][1][0]=(mid-l+1)+maxnum[rc][1][0]; 59 maxnum[num][1][1]=maxnum[rc][1][1]; 60 if(num1[rc]==r-mid) maxnum[num][1][1]=(r-mid)+maxnum[lc][1][1]; 61 maxnum[num][0][2]=max(max(maxnum[lc][0][2],maxnum[rc][0][2]),maxnum[lc][0][1]+maxnum[rc][0][0]); 62 maxnum[num][1][2]=max(max(maxnum[lc][1][2],maxnum[rc][1][2]),maxnum[lc][1][1]+maxnum[rc][1][0]); 63 } 64 void build(int l,int r,int num) 65 { 66 if(l==r) 67 { 68 num1[num]=(a[l]==1); 69 maxnum[num][0][0]=maxnum[num][0][1]=maxnum[num][0][2]=(a[l]==0); 70 maxnum[num][1][0]=maxnum[num][1][1]=maxnum[num][1][2]=(a[l]==1); 71 settag[num]=-1; 72 return; 73 } 74 build(l,mid,lc); 75 build(mid+1,r,rc); 76 settag[num]=-1;update(l,r,num); 77 } 78 void setto(int l,int r,int num) 79 { 80 if(L<=l&&r<=R) 81 { 82 revtag[num]=0;settag[num]=x; 83 num1[num]=x*(r-l+1);//mid-l+1 84 maxnum[num][0][0]=maxnum[num][0][1]=maxnum[num][0][2]=(1-x)*(r-l+1);//mid-l+1 85 maxnum[num][1][0]=maxnum[num][1][1]=maxnum[num][1][2]=x*(r-l+1);//mid-l+1 86 return; 87 } 88 pd(l,r,num); 89 if(L<=mid) setto(l,mid,lc); 90 if(mid<R) setto(mid+1,r,rc); 91 update(l,r,num); 92 } 93 void revx(int l,int r,int num) 94 { 95 if(L<=l&&r<=R) 96 { 97 revtag[num]^=1; 98 num1[num]=r-l+1-num1[num]; 99 swap(maxnum[num][0][0],maxnum[num][1][0]); 100 swap(maxnum[num][0][1],maxnum[num][1][1]); 101 swap(maxnum[num][0][2],maxnum[num][1][2]); 102 return; 103 } 104 pd(l,r,num); 105 if(L<=mid) revx(l,mid,lc); 106 if(mid<R) revx(mid+1,r,rc); 107 update(l,r,num); 108 } 109 int query1(int l,int r,int num) 110 { 111 if(L<=l&&r<=R) return num1[num]; 112 pd(l,r,num); 113 int ans=0; 114 if(L<=mid) ans+=query1(l,mid,lc); 115 if(mid<R) ans+=query1(mid+1,r,rc); 116 return ans; 117 } 118 Th query2(int l,int r,int num) 119 { 120 //if(L<=l&&r<=R) return Th(maxnum[num][1][0],maxnum[num][1][1],maxnum[num][1][2],num1[num]==r-l+1,1); 121 if(L<=l&&r<=R) return Th(maxnum[num][1][0],maxnum[num][1][1],maxnum[num][1][2],num1[num]==r-l+1,r-l+1);//num1[num]==1 122 pd(l,r,num); 123 Th ans,t1,t2; 124 if(L<=mid) t1=query2(l,mid,lc); 125 if(mid<R) t2=query2(mid+1,r,rc); 126 ans.a=t1.a; 127 //if(t1.d||t1.len==0) ans.a=t1.len+t2.a; 128 if(t1.d) ans.a=t1.len+t2.a; 129 ans.b=t2.b; 130 //if(t2.d||t2.len==0) ans.b=t2.len+t1.b; 131 if(t2.d) ans.b=t2.len+t1.b; 132 ans.c=max(max(t1.c,t2.c),t1.b+t2.a); 133 ans.d=t1.d&&t2.d; 134 ans.len=t1.len+t2.len; 135 return ans; 136 } 137 int main() 138 { 139 int i,idx;Th ttt; 140 scanf("%d%d",&n,&m); 141 for(i=1;i<=n;i++) scanf("%d",&a[i]); 142 build(1,n,1); 143 for(i=1;i<=m;i++) 144 { 145 scanf("%d%d%d",&idx,&L,&R);L++,R++; 146 if(idx==0) x=0,setto(1,n,1); 147 else if(idx==1) x=1,setto(1,n,1); 148 else if(idx==2) revx(1,n,1); 149 else if(idx==3) printf("%d\n",query1(1,n,1)); 150 else if(idx==4) {ttt=query2(1,n,1);printf("%d\n",max(max(ttt.a,ttt.b),ttt.c));} 151 } 152 return 0; 153 }

bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572