题目意思很简单,四种操作:全部变成1,全部变成0,或者区间异或,查询区间1的个数,和区间连续的1的最大长度。理解起来没有问题,可是写起代码来发现非常繁琐,共用了9个数组,差不多200行了,第一次写这么长得代码,WA一次,后来发现某个地方rt<<1,写成了rt<<1|1,还有PushUp向上更新时忘记了cover[rt]也要根据sum[rt]的值进行更新。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #define N 111111 6 #define lson l,m,rt<<1 7 #define rson m+1,r,rt<<1|1 8 using namespace std; 9 10 int sum[N<<2],msum[N<<2],lsum[N<<2],rsum[N<<2],XOR[N<<2],cover[N<<2],msum0[N<<2],lsum0[N<<2],rsum0[N<<2]; 11 12 13 //sum表示区间1的个数,msum表示区间连续1的最大长度,lsum表示从左端开始的1的最大长度, 14 //XOR为异或标记,cover为覆盖标记,1,0表示区间分别被1,0完全覆盖,-1不完全覆盖 15 //msum0,lsum0,rsum0表示对应的0的个数的统计。 16 17 18 void PushUp(int rt,int m) 19 { 20 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 21 cover[rt]=((sum[rt]==m)?1:((sum[rt]==0)?0:-1)); 22 lsum[rt]=lsum[rt<<1];//我擦 23 rsum[rt]=rsum[rt<<1|1]; 24 lsum0[rt]=lsum0[rt<<1]; 25 rsum0[rt]=rsum0[rt<<1|1]; 26 if(lsum[rt]==(m-(m>>1))) 27 lsum[rt]+=lsum[rt<<1|1]; 28 else if(lsum0[rt]==(m-(m>>1))) 29 lsum0[rt]+=lsum0[rt<<1|1]; 30 if(rsum[rt]==(m>>1)) 31 rsum[rt]+=rsum[rt<<1]; 32 else if(rsum0[rt]==(m>>1)) 33 rsum0[rt]+=rsum0[rt<<1]; 34 msum0[rt]=max(max(msum0[rt<<1],msum0[rt<<1|1]),rsum0[rt<<1]+lsum0[rt<<1|1]); 35 msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]); 36 } 37 38 void FXOR(int rt,int m) 39 { 40 if(cover[rt]!=-1) 41 { 42 cover[rt]^=1; 43 sum[rt]=msum[rt]=lsum[rt]=rsum[rt]=m*cover[rt]; 44 msum0[rt]=lsum0[rt]=rsum0[rt]=m*(1-cover[rt]); 45 } 46 else 47 { 48 XOR[rt]^=1; 49 sum[rt]=(m-sum[rt]); 50 int a=lsum[rt],b=rsum[rt]; 51 lsum[rt]=lsum0[rt]; 52 rsum[rt]=rsum0[rt]; 53 lsum0[rt]=a; 54 rsum0[rt]=b; 55 a=msum[rt]; 56 msum[rt]=msum0[rt]; 57 msum0[rt]=a; 58 } 59 } 60 61 void PushDown(int rt,int m) 62 { 63 if(cover[rt]!=-1) 64 { 65 lsum[rt<<1]=rsum[rt<<1]=msum[rt<<1]=sum[rt<<1]=(m-(m>>1))*cover[rt]; 66 lsum[rt<<1|1]=rsum[rt<<1|1]=msum[rt<<1|1]=sum[rt<<1|1]=(m>>1)*cover[rt]; 67 lsum0[rt<<1]=rsum0[rt<<1]=msum0[rt<<1]=(m-(m>>1))*(1-cover[rt]); 68 lsum0[rt<<1|1]=rsum0[rt<<1|1]=msum0[rt<<1|1]=(m>>1)*(1-cover[rt]); 69 cover[rt<<1]=cover[rt<<1|1]=cover[rt]; 70 XOR[rt<<1]=XOR[rt<<1|1]=0; 71 cover[rt]=-1; 72 } 73 if(XOR[rt]) 74 { 75 FXOR(rt<<1,(m-(m>>1))); 76 FXOR(rt<<1|1,(m>>1)); 77 XOR[rt]=0; 78 } 79 80 } 81 82 void build(int l,int r,int rt) 83 { 84 XOR[rt]=0; 85 if(l==r) 86 { 87 scanf("%d",&sum[rt]); 88 lsum[rt]=rsum[rt]=msum[rt]=cover[rt]=sum[rt]; 89 lsum0[rt]=rsum0[rt]=msum0[rt]=1-sum[rt]; 90 return; 91 } 92 int m=(l+r)>>1; 93 build(lson); 94 build(rson); 95 PushUp(rt,r-l+1); 96 } 97 98 void update(int L,int R,int c,int l,int r,int rt) 99 { 100 if(L<=l&&R>=r) 101 { 102 if(c==0) 103 cover[rt]=0,lsum[rt]=rsum[rt]=sum[rt]=msum[rt]=0,lsum0[rt]=rsum0[rt]=msum0[rt]=r-l+1,XOR[rt]=0; 104 else if(c==1) 105 cover[rt]=1,lsum[rt]=rsum[rt]=sum[rt]=msum[rt]=r-l+1,lsum0[rt]=rsum0[rt]=msum0[rt]=0,XOR[rt]=0; 106 else FXOR(rt,r-l+1); 107 return; 108 } 109 int m=(l+r)>>1; 110 PushDown(rt,r-l+1); 111 if(L<=m) 112 update(L,R,c,lson); 113 if(R>m) 114 update(L,R,c,rson); 115 PushUp(rt,r-l+1); 116 } 117 118 int query1(int L,int R,int l,int r,int rt) 119 { 120 if(L<=l&&R>=r) 121 return sum[rt]; 122 int m=(l+r)>>1; 123 PushDown(rt,r-l+1); 124 int res=0; 125 if(L<=m) 126 res+=query1(L,R,lson); 127 if(R>m) 128 res+=query1(L,R,rson); 129 return res; 130 } 131 132 int query2(int L,int R,int l,int r,int rt) 133 { 134 if(L<=l&&R>=r) 135 return msum[rt]; 136 int m=(l+r)>>1; 137 PushDown(rt,r-l+1); 138 int ans=0; 139 if(R<=m) 140 ans=max(ans,query2(L,R,lson)); 141 else if(L>m) 142 ans=max(ans,query2(L,R,rson)); 143 else 144 { 145 ans=max(ans,query2(L,R,lson)); 146 ans=max(ans,query2(L,R,rson)); 147 int ll,rr; 148 ll=min(m-L+1,rsum[rt<<1]); 149 rr=min(R-m,lsum[rt<<1|1]); 150 ans=max(ans,ll+rr); 151 } 152 return ans; 153 } 154 155 int main(void) 156 { 157 int tc,n,m; 158 int op,a,b,ans; 159 scanf("%d",&tc); 160 while(tc--) 161 { 162 scanf("%d%d",&n,&m); 163 build(1,n,1); 164 while(m--) 165 { 166 scanf("%d%d%d",&op,&a,&b); 167 switch(op) 168 { 169 case 0: 170 case 1: 171 case 2: 172 update(a+1,b+1,op,1,n,1); 173 break; 174 case 3: 175 ans=query1(a+1,b+1,1,n,1); 176 printf("%d\n",ans); 177 break; 178 case 4: 179 ans=query2(a+1,b+1,1,n,1); 180 printf("%d\n",ans); 181 break; 182 } 183 } 184 } 185 return 0; 186 }