HDU 3397 线段树 较麻烦
2013-09-04 16:15
239 查看
3911的升级版
同时要做两种LAZY操作,一定要先做COVER,否则会WA,因为COVER可以覆盖之前的XOR
同时要做两种LAZY操作,一定要先做COVER,否则会WA,因为COVER可以覆盖之前的XOR
#include "stdio.h" #include "string.h" #include "math.h" #include "stdlib.h" #include "algorithm" using namespace std; struct comp { int l,r,mid; int l1,l0; // 记录区间内从最左端起连续1和0个数 int r1,r0; // 记录区间内从最右端起连续1和0个数 int m1,m0; // 记录区间内最长连续1和0个数 int cover; // lazy操作的覆盖 int xor; // lazy操作的变换 int sum; // 区间内1的总数 } data[300005]; int max(int a,int b) { if (a<b) return b; else return a; } void PushUp(int k) { int ll,rr; ll=data[k*2].r-data[k*2].l+1; rr=data[k*2+1].r-data[k*2+1].l+1; data[k].sum=data[k*2].sum+data[k*2+1].sum; data[k].l1=data[k*2].l1; if (data[k].l1==ll) data[k].l1+=data[k*2+1].l1; data[k].l0=data[k*2].l0; if (data[k].l0==ll) data[k].l0+=data[k*2+1].l0; data[k].r1=data[k*2+1].r1; if (data[k].r1==rr) data[k].r1+=data[k*2].r1; data[k].r0=data[k*2+1].r0; if (data[k].r0==rr) data[k].r0+=data[k*2].r0; data[k].m1=max( max(data[k*2].m1,data[k*2+1].m1) , data[k*2].r1+data[k*2+1].l1); data[k].m0=max( max(data[k*2].m0,data[k*2+1].m0) , data[k*2].r0+data[k*2+1].l0); } void build(int l,int r,int k) { int x; data[k].l=l; data[k].r=r; data[k].mid=(l+r)/2; data[k].xor=0; data[k].cover=-1; if (l==r) { scanf("%d",&x); if (x==1) { data[k].l1=data[k].r1=data[k].m1=1; data[k].l0=data[k].r0=data[k].m0=0; data[k].sum=1; data[k].cover=1; } else { data[k].l1=data[k].r1=data[k].m1=0; data[k].l0=data[k].r0=data[k].m0=1; data[k].sum=0; data[k].cover=0; } return ; } build(l,data[k].mid,k*2); build(data[k].mid+1,r,k*2+1); PushUp(k); } void PushDown(int k) // 重点是两种LAZY操作的顺序,必须先做COVER操作 { int ll,rr; if (data[k].l==data[k].r) return ; ll=data[k*2].r-data[k*2].l+1; rr=data[k*2+1].r-data[k*2+1].l+1; if (data[k].cover!=-1) { data[k*2].cover=data[k*2+1].cover=data[k].cover; data[k*2].xor=data[k*2+1].xor=0; if (data[k].cover==1) { data[k*2].sum=ll; data[k*2+1].sum=rr; data[k*2].l1=data[k*2].r1=data[k*2].m1=ll; data[k*2].l0=data[k*2].r0=data[k*2].m0=0; data[k*2+1].l1=data[k*2+1].r1=data[k*2+1].m1=rr; data[k*2+1].l0=data[k*2+1].r0=data[k*2+1].m0=0; } if (data[k].cover==0) { data[k*2].sum=data[k*2+1].sum=0; data[k*2].l1=data[k*2].r1=data[k*2].m1=0; data[k*2].l0=data[k*2].r0=data[k*2].m0=ll; data[k*2+1].l1=data[k*2+1].r1=data[k*2+1].m1=0; data[k*2+1].l0=data[k*2+1].r0=data[k*2+1].m0=rr; } data[k].cover=-1; } if (data[k].xor%2==1) { data[k].xor=0; data[k*2].xor++; data[k*2+1].xor++; data[k*2].sum=ll-data[k*2].sum; data[k*2+1].sum=rr-data[k*2+1].sum; swap(data[k*2].l1,data[k*2].l0); swap(data[k*2].r1,data[k*2].r0); swap(data[k*2].m1,data[k*2].m0); swap(data[k*2+1].l1,data[k*2+1].l0); swap(data[k*2+1].r1,data[k*2+1].r0); swap(data[k*2+1].m1,data[k*2+1].m0); } } void update(int l,int r,int k,int op) { int le; PushDown(k); if (data[k].l==l && data[k].r==r ) { le=data[k].r-data[k].l+1; if (op==0) { data[k].cover=0; data[k].sum=0; data[k].l1=data[k].r1=data[k].m1=0; data[k].l0=data[k].r0=data[k].m0=le; data[k].xor=0; } if (op==1) { data[k].cover=1; data[k].sum=le; data[k].l1=data[k].r1=data[k].m1=le; data[k].l0=data[k].r0=data[k].m0=0; data[k].xor=0; } if (op==2) { if (data[k].cover!=-1) data[k].cover=(data[k].cover+1)%2; data[k].sum=le-data[k].sum; swap(data[k].l1,data[k].l0); swap(data[k].r1,data[k].r0); swap(data[k].m1,data[k].m0); data[k].xor++; } return ; } if (r<=data[k].mid) update(l,r,k*2,op); else if (l>data[k].mid) update(l,r,k*2+1,op); else { update(l,data[k].mid,k*2,op); update(data[k].mid+1,r,k*2+1,op); } PushUp(k); } int query(int l,int r,int k,int op) { int aa,bb,ll,rr; if (data[k].l==l && data[k].r==r) { if (op==3) return data[k].sum; else return data[k].m1; } PushDown(k); if (r<=data[k].mid) return query(l,r,k*2,op); else if (l>data[k].mid) return query(l,r,k*2+1,op); else { if (op==3) return query(l,data[k].mid,k*2,op)+query(data[k].mid+1,r,k*2+1,op); else { aa=query(l,data[k].mid,k*2,op); bb=query(data[k].mid+1,r,k*2+1,op); ll=data[k*2].r1; if (ll>data[k*2].r-l+1) ll=data[k*2].r-l+1; rr=data[k*2+1].l1; if (rr>r-data[k*2+1].l+1) rr=r-data[k*2+1].l+1; return max(max(aa,bb),ll+rr); } } } int main() { int t,n,m,a,b,c; scanf("%d",&t); while (t--) { scanf("%d%d",&n,&m); build(1,n,1); while (m--) { scanf("%d%d%d",&a,&b,&c); b++; c++; if (a<=2) update(b,c,1,a); else printf("%d\n",query(b,c,1,a)); } } return 0; }
相关文章推荐
- 【线段树】HDU 3397 Sequence operation 区间合并
- HDU 3397 线段树 双懒惰标记
- 【线段树】HDU 3397 Sequence operation 区间合并
- HDU 3397 Sequence operation(线段树)
- Hdu 3397 Sequence operation(线段树多操作,Lazy思想,成段更新)
- HDU 3397 Sequence operation(线段树好题)
- hdu 3397 Sequence operation(很有意思的线段树题)
- HDU 3397 线段树区间合并
- HDU 3397 线段树区间染色 区间查询
- hdu 3397 Sequence Operation 线段树维护区间前后缀和,求子区间连续最值
- hdu 3397 复杂线段树
- HDU 3397 Sequence operation 线段树
- HDU 3397 Sequence operation 线段树综合题
- hdu 3397 线段树
- HDU 3397 - Sequence operation(线段树+区间合并)
- hdu 3397 Sequence operation 线段树
- HDU 3397 Sequence operation (线段树)
- HDU - 3397 Sequence operation(线段树)
- HDU 3397 Sequence operation (线段树)
- HDU 3397 Sequence operation (线段树,成段更新,区间合并)