bzoj 1858: [Scoi2010]序列操作 || 洛谷 P2572
记一下:线段树占空间是$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 }