Sequence operation HDU 3397
题意:一串0,1代码,5中操作:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
题解:线段树的各种操作:区间更新+区间合并+延迟标记。。。
每个节点记录八个值:lsum0,rsum0,msum0,lsum1,rsum1,msum1,num,cov.分别为区间左端连续0的个数,区间右端连续0的个数,区间连续0的最大个数,和区间左端连续1的个数,区间右端连续1的个数,区间最大连续1的个数以及区间1的总个数和区间覆盖情况。
这题算是一个小小的总结了吧。。。题目很简单,但是因为之前有些东西还没有特别熟练,所以写代码的时候出现了个很难发现的bug,一直WA啊,RE的,所以找了很长很长时间才排除掉。。。这里记录一下,以示警醒。
之前的错误代码问题出现在更新操作2上,即异或操作。
1 void updata(int L,int R,int op,int l,int r,int rt){ 2 if(L<=l&&r<=R){ 3 int m=r-l+1; 4 if(op==0){ 5 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=0; 6 lsum0[rt]=rsum0[rt]=msum0[rt]=m; 7 cov[rt]=0; 8 } 9 else if(op==1){ 10 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=m; 11 lsum0[rt]=rsum0[rt]=msum0[rt]=0; 12 cov[rt]=1; 13 } 14 else{//错误就出现在这。。。 15 if(l==r){ 16 XOR(l,r,rt); 17 return ; 18 } 19 if(cov[rt]!=-1)pushDown(l,r,rt); 20 XOR(l,r,rt); 21 cov[rt]=2; 22 } 23 return ; 24 } 25 int m=(l+r)>>1; 26 if(cov[rt]!=-1) pushDown(l,r,rt); 27 if(R<=m) updata(L,R,op,lson); 28 else if(L>m) updata(L,R,op,rson); 29 else{ 30 updata(L,R,op,lson); 31 updata(L,R,op,rson); 32 } 33 pushUp(rt,r-l+1); 34 }
之前我认为在进行2操作时只要先进行pushDown在XOR即可,实际上这是有问题的:因为下次再pushDown时就会把上次pushDown传递下去的结果覆盖掉!因此对于更新时的XOR操作正确的做法是:先XOR当前区间,再修改cov[]的值。当cov[rt]为0是改为1,为0是改为1为2时改为-1,为-1时改为2。
即如下:
1 void updata(int L,int R,int op,int l,int r,int rt){ 2 if(L<=l&&r<=R){ 3 int len=r-l+1; 4 if(op==0){ 5 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=0; 6 lsum0[rt]=rsum0[rt]=msum0[rt]=len; 7 cov[rt]=0; 8 } 9 else if(op==1){ 10 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=len; 11 lsum0[rt]=rsum0[rt]=msum0[rt]=0; 12 cov[rt]=1; 13 } 14 else{//改成这样: 15 XOR(rt,len); 16 if(cov[rt]==0) cov[rt]=1; 17 else if(cov[rt]==1) cov[rt]=0; 18 else if(cov[rt]==-1)cov[rt]=2; 19 else cov[rt]=-1; 20 } 21 return ; 22 } 23 if(cov[rt]!=-1) pushDown(rt,r-l+1); 24 int m=(l+r)>>1; 25 if(R<=m) updata(L,R,op,lson); 26 else if(L>m) updata(L,R,op,rson); 27 else{ 28 updata(L,R,op,lson); 29 updata(L,R,op,rson); 30 } 31 pushUp(rt,r-l+1); 32 }
当然其他地方涉及到XOR的操作也要进行相应的修改啦。。。
具体代码如下(操作比较多,所以代码就有点长啦~~~)
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 #define lson l,m,rt<<1 6 #define rson m+1,r,rt<<1|1 7 using namespace std; 8 9 const int maxn=1000005; 10 int lsum1[maxn<<2],rsum1[maxn<<2],msum1[maxn<<2],lsum0[maxn<<2],rsum0[maxn<<2],msum0[maxn<<2],num[maxn<<2],cov[maxn<<2]; 11 12 int max(int a,int b){ 13 return a>b?a:b; 14 } 15 16 int min(int a,int b){ 17 return a<b?a:b; 18 } 19 20 void pushUp(int rt,int len){ 21 lsum1[rt]=lsum1[rt<<1]; 22 rsum1[rt]=rsum1[rt<<1|1]; 23 msum1[rt]=max(msum1[rt<<1],msum1[rt<<1|1]); 24 25 lsum0[rt]=lsum0[rt<<1]; 26 rsum0[rt]=rsum0[rt<<1|1]; 27 msum0[rt]=max(msum0[rt<<1],msum0[rt<<1|1]); 28 29 num[rt]=num[rt<<1]+num[rt<<1|1]; 30 31 if(lsum1[rt]==len-(len>>1)) lsum1[rt]+=lsum1[rt<<1|1]; 32 if(rsum1[rt]==(len>>1)) rsum1[rt]+=rsum1[rt<<1]; 33 if(lsum0[rt]==len-(len>>1)) lsum0[rt]+=lsum0[rt<<1|1]; 34 if(rsum0[rt]==(len>>1)) rsum0[rt]+=rsum0[rt<<1]; 35 msum1[rt]=max(msum1[rt],lsum1[rt<<1|1]+rsum1[rt<<1]); 36 msum0[rt]=max(msum0[rt],lsum0[rt<<1|1]+rsum0[rt<<1]); 37 } 38 39 void build(int l,int r,int rt){ 40 cov[rt]=-1; 41 if(l==r){ 42 int x; 43 scanf("%d",&x); 44 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=x?1:0; 45 lsum0[rt]=rsum0[rt]=msum0[rt]=x?0:1; 46 return ; 47 } 48 int m=(l+r)>>1; 49 build(lson); 50 build(rson); 51 pushUp(rt,r-l+1); 52 } 53 54 void XOR(int rt,int len){ 55 swap(lsum0[rt],lsum1[rt]); 56 swap(rsum0[rt],rsum1[rt]); 57 swap(msum0[rt],msum1[rt]); 58 num[rt]=len-num[rt]; 59 } 60 61 void pushDown(int rt,int len){ 62 if(cov[rt]==0){ 63 lsum1[rt<<1]=rsum1[rt<<1]=msum1[rt<<1]=num[rt<<1]=lsum1[rt<<1|1]=rsum1[rt<<1|1]=msum1[rt<<1|1]=num[rt<<1|1]=0; 64 lsum0[rt<<1]=rsum0[rt<<1]=msum0[rt<<1]=len-(len>>1); 65 lsum0[rt<<1|1]=rsum0[rt<<1|1]=msum0[rt<<1|1]=(len>>1); 66 cov[rt<<1]=cov[rt<<1|1]=cov[rt]; 67 cov[rt]=-1; 68 } 69 else if(cov[rt]==1){ 70 lsum1[rt<<1]=rsum1[rt<<1]=msum1[rt<<1]=len-(len>>1); 71 lsum1[rt<<1|1]=rsum1[rt<<1|1]=msum1[rt<<1|1]=(len>>1); 72 lsum0[rt<<1]=rsum0[rt<<1]=msum0[rt<<1]=lsum0[rt<<1|1]=rsum0[rt<<1|1]=msum0[rt<<1|1]=0; 73 num[rt<<1]=len-(len>>1);num[rt<<1|1]=(len>>1); 74 cov[rt<<1]=cov[rt<<1|1]=cov[rt]; 75 cov[rt]=-1; 76 } 77 else{ 78 XOR(rt<<1,len-(len>>1)); 79 if(cov[rt<<1]==0) cov[rt<<1]=1; 80 else if(cov[rt<<1]==1) cov[rt<<1]=0; 81 else if(cov[rt<<1]==2) cov[rt<<1]=-1; 82 else cov[rt<<1]=2; 83 84 XOR(rt<<1|1,(len>>1)); 85 if(cov[rt<<1|1]==0) cov[rt<<1|1]=1; 86 else if(cov[rt<<1|1]==1) cov[rt<<1|1]=0; 87 else if(cov[rt<<1|1]==2) cov[rt<<1|1]=-1; 88 else cov[rt<<1|1]=2; 89 cov[rt]=-1; 90 } 91 } 92 93 void updata(int L,int R,int op,int l,int r,int rt){ 94 if(L<=l&&r<=R){ 95 int len=r-l+1; 96 if(op==0){ 97 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=0; 98 lsum0[rt]=rsum0[rt]=msum0[rt]=len; 99 cov[rt]=0; 100 } 101 else if(op==1){ 102 lsum1[rt]=rsum1[rt]=msum1[rt]=num[rt]=len; 103 lsum0[rt]=rsum0[rt]=msum0[rt]=0; 104 cov[rt]=1; 105 } 106 else{ 107 XOR(rt,len); 108 if(cov[rt]==0) cov[rt]=1; 109 else if(cov[rt]==1) cov[rt]=0; 110 else if(cov[rt]==-1)cov[rt]=2; 111 else cov[rt]=-1; 112 } 113 return ; 114 } 115 if(cov[rt]!=-1) pushDown(rt,r-l+1); 116 int m=(l+r)>>1; 117 if(R<=m) updata(L,R,op,lson); 118 else if(L>m) updata(L,R,op,rson); 119 else{ 120 updata(L,R,op,lson); 121 updata(L,R,op,rson); 122 } 123 pushUp(rt,r-l+1); 124 } 125 126 int query1(int L,int R,int l,int r,int rt){ 127 if(L<=l&&r<=R) return num[rt]; 128 if(cov[rt]!=-1) pushDown(rt,r-l+1); 129 int m=(l+r)>>1; 130 if(R<=m) return query1(L,R,lson); 131 else if(L>m) return query1(L,R,rson); 132 else return query1(L,R,lson)+query1(L,R,rson); 133 } 134 135 int query2(int L,int R,int l,int r,int rt){ 136 if(L<=l&&r<=R) return msum1[rt]; 137 if(cov[rt]!=-1) pushDown(rt,r-l+1); 138 int m=(l+r)>>1; 139 if(R<=m) return query2(L,R,lson); 140 else if(L>m) return query2(L,R,rson); 141 else{ 142 int ta=query2(L,R,lson); 143 int tb=query2(L,R,rson); 144 int temp=max(ta,tb); 145 int ans=min(m-L+1,rsum1[rt<<1])+min(R-m,lsum1[rt<<1|1]); 146 return max(ans,temp); 147 } 148 } 149 150 int main() 151 { 152 //freopen("in.txt","r",stdin); 153 int T,n,m,a,b,op; 154 scanf("%d",&T); 155 while(T--){ 156 scanf("%d %d",&n,&m); 157 build(1,n,1); 158 while(m--){ 159 scanf("%d %d %d",&op,&a,&b); 160 if(op<3) updata(a+1,b+1,op,1,n,1); 161 else if(op==3) printf("%d\n",query1(a+1,b+1,1,n,1)); 162 else printf("%d\n",query2(a+1,b+1,1,n,1)); 163 } 164 } 165 return 0; 166 }
posted on 2012-11-13 12:11 Acmer_Roney 阅读(228) 评论(0) 编辑 收藏 举报