HDU 3397 线段树 较麻烦
来源:互联网 发布:sql查询例子 编辑:程序博客网 时间:2024/04/30 03:43
3911的升级版
同时要做两种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 线段树 较麻烦
- HDU 3397(线段树,较难~)
- hdu 3397 复杂线段树
- XTU1238Segment Tree(线段树)解题思想必较经典
- zoj3813 Alternating Sum 较难的线段树
- hdu 3397(线段树区间合并)
- 线段树 HDU 3397 Sequence operation
- 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 线段树
- hdu 3397 Sequence operation(线段树)
- HDU 3397 Sequence operation(线段树)
- python+tornado+sae 饭否--订餐系统
- js格式化货币数据
- <Linux+Qt>QDialog的模态与非模态的对话框
- 再谈 ---- IP地址
- 程序员与妓女基本一样
- HDU 3397 线段树 较麻烦
- qemu的网络模式
- PHP时间戳函数总结一览
- VS2010Silverlight调用Wcf配置说明
- 用WinRar实现将多个安装包打成一个安装包
- JQuery知识点整理
- HTML 续复习
- Lucene学习笔记(4):Lucene Index 删除、更新
- CCSpriteBatchNode提高渲染效率的用法