poj-3397【线段树区间合并】
不得不说线段树的问题代码真太长。。。。。。
这个问题大意刚开始给出一个区间内的数,要么是0要么是1;
然后有如下操作:
0 i j:把区间i到j内的数全部变成0
1 i j:把区间i到j内的数全部变成1
2 i j:把区间i到j内的数0变成1,1变成0
3 i j:把区间i到j内的所有的1求出来
4 i j:求出区间i到j内最大连续的1;
这个问题的关键其实是操作2,因为这涉及到区间更新,所以会用到懒惰标记,用懒惰标记时,到2操作的时候,不能把原来的标记覆盖掉
而是应该对于原来的标记取反,,,,这个地方懂了也就没问题了。。。
(不过刚开始我还出现一个问题,对于两个求值得操作求法不一样,,,这个注意!!)
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 100010 using namespace std; struct node { int lm; int rm; int lom; int rom; int res1; int res2; int all1; int all2; }; node tree[4*maxn]; int tag[4*maxn]; int flag[maxn]; void XOR(int now) { if (tag[now]==0)tag[now]=1; else if (tag[now]==1)tag[now]=0; else if (tag[now]==2)tag[now]=-1;//!!!这是取反,不是覆盖!! else if (tag[now]==-1)tag[now]=2; } void up(int now,int l,int r) { tree[now].lm=tree[2*now].lm; tree[now].rm=tree[2*now+1].rm; tree[now].lom=tree[2*now].lom; tree[now].rom=tree[2*now+1].rom; tree[now].res1=max(tree[2*now].res1,tree[2*now+1].res1); tree[now].res2=max(tree[2*now].res2,tree[2*now+1].res2); tree[now].all1=tree[2*now].all1+tree[2*now+1].all1; tree[now].all2=tree[2*now].all2+tree[2*now+1].all2; int mid=(l+r)>>1; if(tree[2*now].lm==(mid-l+1)) { tree[now].lm+=tree[2*now+1].lm; } if (tree[2*now+1].rm==r-mid) { tree[now].rm+=tree[2*now].rm; } if (tree[2*now].lom==(mid-l+1)) { tree[now].lom+=tree[2*now+1].lom; } if (tree[2*now+1].rom==r-mid) { tree[now].rom+=tree[2*now].rom; } tree[now].res1=max(tree[now].res1,tree[2*now].rm+tree[2*now+1].lm); tree[now].res2=max(tree[now].res2,tree[2*now].rom+tree[2*now+1].lom); } void down(int now,int l,int r) { if (tag[now]==-1)return ; int mid=(l+r)>>1; if (tag[now]==1) { tag[2*now]=tag[2*now+1]=tag[now]; tree[2*now].lm=tree[2*now].rm=tree[2*now].res1=tree[2*now].all1=mid-l+1; tree[2*now+1].lm=tree[2*now+1].rm=tree[2*now+1].res1=tree[2*now+1].all1=r-mid; tree[2*now].lom=tree[2*now].rom=tree[2*now].res2=tree[2*now].all2=0; tree[2*now+1].lom=tree[2*now+1].rom=tree[2*now+1].res2=tree[2*now+1].all2=0; tag[now]=-1; } else if (tag[now]==0) { tag[2*now]=tag[2*now+1]=tag[now]; tree[2*now].lm=tree[2*now].rm=tree[2*now].res1=tree[2*now].all1=0; tree[2*now+1].lm=tree[2*now+1].rm=tree[2*now+1].res1=tree[2*now+1].all1=0; tree[2*now].lom=tree[2*now].rom=tree[2*now].res2=tree[2*now].all2=mid-l+1; tree[2*now+1].lom=tree[2*now+1].rom=tree[2*now+1].res2=tree[2*now+1].all2=r-mid; tag[now]=-1; } else if (tag[now]==2) { swap(tree[2*now].lm,tree[2*now].lom); swap(tree[2*now].rm,tree[2*now].rom); swap(tree[2*now].res1,tree[2*now].res2); swap(tree[2*now].all1,tree[2*now].all2); swap(tree[2*now+1].lm,tree[2*now+1].lom); swap(tree[2*now+1].rm,tree[2*now+1].rom); swap(tree[2*now+1].res1,tree[2*now+1].res2); swap(tree[2*now+1].all1,tree[2*now+1].all2); XOR(2*now); XOR(2*now+1);//注意这两个XOR,就是防止区间被覆盖的 tag[now]=-1; } } void build(int now,int l,int r) { tag[now]=-1; if(l==r) { tree[now].lm=tree[now].rm=tree[now].res1=tree[now].all1=(flag[l]==0?0:1); tree[now].lom=tree[now].rom=tree[now].res2=tree[now].all2=(flag[l]==0?1:0); return ; } int mid=(l+r)>>1; build(2*now,l,mid); build(2*now+1,mid+1,r); up(now,l,r); } void update(int now,int l,int r,int tl,int tr,int val) { if (tl<=l&&tr>=r) { if (val==0) { tree[now].lm=tree[now].rm=tree[now].res1=tree[now].all1=0; tree[now].lom=tree[now].rom=tree[now].res2=tree[now].all2=(r-l+1); tag[now]=val; } else if (val==1) { tree[now].lm=tree[now].rm=tree[now].res1=tree[now].all1=(r-l+1); tree[now].lom=tree[now].rom=tree[now].res2=tree[now].all2=0; tag[now]=val; } else { swap(tree[now].lm,tree[now].lom); swap(tree[now].rm,tree[now].rom); swap(tree[now].res1,tree[now].res2); swap(tree[now].all1,tree[now].all2); XOR(now);//这个也是!!! } return ; } down(now,l,r); int mid=(l+r)>>1; if (tr<=mid) { update(2*now,l,mid,tl,tr,val); } else if (tl>mid) { update(2*now+1,mid+1,r,tl,tr,val); } else { update(2*now,l,mid,tl,mid,val); update(2*now+1,mid+1,r,mid+1,tr,val); } up(now,l,r); } int query(int now,int l,int r,int tl,int tr,int val) { if (tl<=l&&tr>=r) { if (val==3) { return tree[now].all1; } if (val==4) { return tree[now].res1; } } down(now,l,r); int mid=(l+r)>>1; if (tr<=mid) { return query(2*now,l,mid,tl,tr,val); } else if (tl>mid) { return query(2*now+1,mid+1,r,tl,tr,val); } else { if (val==3) { int t1=query(2*now,l,mid,tl,tr,val); int t2=query(2*now+1,mid+1,r,tl,tr,val); return t1+t2; } else { int t1=query(2*now,l,mid,tl,tr,val); int t2=query(2*now+1,mid+1,r,tl,tr,val); int t=max(t1,t2); t1=min(tree[2*now].rm,mid-tl+1);// t2=min(tree[2*now+1].lm,tr-mid); return max(t,t1+t2); } } } int main() { int T,n,m,a,b,c; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&flag[i]); } build(1,1,n); while(m--) { scanf("%d %d %d",&a,&b,&c); if (a<=2) { b++; c++; update(1,1,n,b,c,a); } else { b++; c++; int sum=query(1,1,n,b,c,a); printf("%d\n",sum); } } } return 0; }