poj-3397【线段树区间合并】
来源:互联网 发布:微表情心理学软件 编辑:程序博客网 时间:2024/06/05 11:59
不得不说线段树的问题代码真太长。。。。。。
这个问题大意刚开始给出一个区间内的数,要么是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 100010using 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;}
0 0
- poj-3397【线段树区间合并】
- poj 3667 区间合并 区间线段树
- poj 3667【线段树-区间合并】
- POJ 3667 Hotel 线段树区间合并
- poj 3667 Hotel 线段树区间合并
- poj 3667 线段树 区间合并
- poj 2892 线段树 区间合并
- POJ 3667 Hotel 线段树 区间合并
- poj 3667 线段树合并区间
- Poj 3667 Hotel 线段树 区间合并
- POJ Hotel 线段树 区间合并
- POJ 3667-hotel(线段树区间合并)
- poj 3667 线段树,区间合并
- Hotel+POJ+线段树区间合并
- POJ 3667 Hotel. (线段树 区间合并)
- 【线段树】POJ 3667 Hotel 区间合并
- POJ-3667 线段树(区间合并)
- [POJ 1823] Hotel 线段树区间合并
- CSS定位与CSS属性选择器
- JAVASE学习笔记
- 91. Decode Ways
- js中的location.reload()
- openwrt源码结构(装载)
- poj-3397【线段树区间合并】
- 如何利用nginx或tomcat搭建文件服务器
- 第七节表格表单及样式重置、特性
- View的onTouchEvent、setTouchListener、OnClick和setClickListener四者的区别
- 数据库的基本操作之一些基本语句
- 查看正在执行的mysql指令
- Arduino—电机控制
- meta标签中的http-equiv属性使用介绍
- 链栈