感觉自己好像搞定了一个不得了得题呢。。
对于这种区间性质合并的线段树,对于每个节点保存一下当前区间内1的个数,左右边界相邻的1个的个数与0的个数,还有当前区间最大连续的1和0的个数.
合并的时候的细节:
1.如果lson的右边界是1并且rson的左边界是1,那么当前节点的最大连续1的值应该更新为tr[n].res=max(tr[n].res,tr[LL].r+tr[RR].l);
2.如果lson的连续1的个数等于它所表示的区间大小(这段区间的值全为1),那么当前节点的左区间连续1的个数应该更新为tr[n].l+=tr[RR].l;对于右区间的连续1的个数更新也一样。
3.对于区间中0的性质更新与1一样
更新时候的细节
1.如果当前进行的是区间覆盖,那么是需要吧区间翻转的标记置0的。
2.如果当前既需要更新区间覆盖与区间翻转,这时候只有一种可能情况就是区间覆盖是先进行赋值过的,所以在pushdown的时候区间覆盖应该先进行。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL n<<1 4 #define RR n<<1|1 5 #define lson l,mid,LL 6 #define rson mid+1,r,RR 7 #define mid ((l+r)/2) 8 const int maxn=500005; 9 struct node{ 10 int res,ret,num,l,r,ll,rr;//最长连续1的长度,最长连续0的长度,区间内1的个数,区间内左右边界连续1的个数,0的个数 11 }; 12 node tr[maxn<<2]; 13 int lazy[maxn<<2];//区间覆盖懒惰标记 14 int chan[maxn<<2];//区间翻转懒惰标记 15 int a[maxn]; 16 void up(int l,int r,int n){ 17 tr[n].num=tr[LL].num+tr[RR].num; 18 tr[n].res=max(tr[LL].res,tr[RR].res); 19 tr[n].ret=max(tr[LL].ret,tr[RR].ret); 20 tr[n].l=tr[LL].l; 21 tr[n].ll=tr[LL].ll; 22 tr[n].r=tr[RR].r; 23 tr[n].rr=tr[RR].rr; 24 if(tr[LL].r&&tr[RR].l) 25 { 26 tr[n].res=max(tr[n].res,tr[LL].r+tr[RR].l); 27 if(mid-l+1==tr[LL].res) 28 tr[n].l+=tr[RR].l; 29 if(r-mid==tr[RR].res) 30 tr[n].r+=tr[LL].r; 31 } 32 if(tr[LL].rr&&tr[RR].ll) 33 { 34 tr[n].ret=max(tr[n].ret,tr[LL].rr+tr[RR].ll); 35 if(mid-l+1==tr[LL].ret) 36 tr[n].ll+=tr[RR].ll; 37 if(r-mid==tr[RR].ret) 38 tr[n].rr+=tr[LL].rr; 39 } 40 } 41 void built(int l,int r,int n){ 42 lazy[n]=-1; 43 chan[n]=0; 44 if(l==r) 45 { 46 tr[n].l=tr[n].r=tr[n].res=tr[n].num=a[l]; 47 tr[n].ret=tr[n].ll=tr[n].rr=!a[l]; 48 return; 49 } 50 built(lson); 51 built(rson); 52 up(l,r,n); 53 } 54 void pushdown(int l,int r,int n){ 55 if(lazy[n]!=-1) 56 { 57 chan[LL]=chan[RR]=0; 58 tr[LL].num=tr[LL].l=tr[LL].r=tr[LL].res=(mid-l+1)*lazy[n]; 59 tr[LL].ll=tr[LL].rr=tr[LL].ret=(mid-l+1)*(!lazy[n]); 60 tr[RR].num=tr[RR].l=tr[RR].r=tr[RR].res=(r-mid)*lazy[n]; 61 tr[RR].ll=tr[RR].rr=tr[RR].ret=(r-mid)*(!lazy[n]); 62 lazy[LL]=lazy[RR]=lazy[n]; 63 lazy[n]=-1; 64 } 65 if(chan[n]) 66 { 67 chan[LL]^=1; 68 chan[RR]^=1; 69 tr[LL].num=mid-l+1-tr[LL].num; 70 tr[RR].num=r-mid-tr[RR].num; 71 swap(tr[LL].res,tr[LL].ret); 72 swap(tr[LL].ll,tr[LL].l); 73 swap(tr[LL].rr,tr[LL].r); 74 swap(tr[RR].res,tr[RR].ret); 75 swap(tr[RR].ll,tr[RR].l); 76 swap(tr[RR].rr,tr[RR].r); 77 chan[n]=0; 78 } 79 } 80 void update(int l,int r,int n,int left,int right,int num){ 81 if(l>=left&&right>=r) 82 { 83 lazy[n]=num; 84 tr[n].num=num*(r-l+1); 85 chan[n]=0; 86 tr[n].l=tr[n].r=tr[n].res=(r-l+1)*num; 87 tr[n].ll=tr[n].rr=tr[n].ret=(r-l+1)*(!num); 88 return; 89 } 90 pushdown(l,r,n); 91 if(left<=mid) 92 update(lson,left,right,num); 93 if(right>mid) 94 update(rson,left,right,num); 95 up(l,r,n); 96 } 97 void change(int l,int r,int n,int left,int right){ 98 if(l>=left&&right>=r) 99 { 100 chan[n]^=1; 101 tr[n].num=(r-l+1-tr[n].num); 102 swap(tr[n].res,tr[n].ret); 103 swap(tr[n].ll,tr[n].l); 104 swap(tr[n].rr,tr[n].r); 105 return; 106 } 107 pushdown(l,r,n); 108 if(left<=mid) 109 change(lson,left,right); 110 if(right>mid) 111 change(rson,left,right); 112 up(l,r,n); 113 } 114 int out1(int l,int r,int n,int left,int right){ 115 if(l>=left&&right>=r) 116 return tr[n].num; 117 pushdown(l,r,n); 118 int res=0; 119 if(left<=mid) 120 res+=out1(lson,left,right); 121 if(right>mid) 122 res+=out1(rson,left,right); 123 return res; 124 } 125 int out2(int l,int r,int n,int left,int right){ 126 if(l>=left&&right>=r) 127 return tr[n].res; 128 pushdown(l,r,n); 129 int res=0; 130 if(left<=mid) 131 res=max(res,out2(lson,left,right)); 132 if(right>mid) 133 res=max(res,out2(rson,left,right)); 134 if(tr[LL].r&&tr[RR].l&&mid>=left&&mid<right) 135 res=max(res,min(tr[LL].r,mid-left+1)+min(tr[RR].l,right-mid)); 136 return res; 137 } 138 int main(){ 139 int t; 140 scanf("%d",&t); 141 while(t--) 142 { 143 int n,m; 144 scanf("%d%d",&n,&m); 145 for(int i=1;i<=n;i++) 146 scanf("%d",&a[i]); 147 built(1,n,1); 148 for(int i=1;i<=m;i++) 149 { 150 151 int x,y,z; 152 scanf("%d%d%d",&x,&y,&z); 153 y++; 154 z++; 155 if(x==0) 156 update(1,n,1,y,z,0); 157 else 158 if(x==1) 159 update(1,n,1,y,z,1); 160 else 161 if(x==2) 162 change(1,n,1,y,z); 163 if(x==3) 164 printf("%d ",out1(1,n,1,y,z)); 165 else 166 if(x==4) 167 printf("%d ",out2(1,n,1,y,z)); 168 } 169 } 170 return 0; 171 }