hdu3397
来源:互联网 发布:日本女孩知乎 编辑:程序博客网 时间:2024/05/21 14:53
此题中维护操作略多,先说下思路
有两种更新操作set和update分别为设置[a,b]为0或1和求[a,b]反;
1.每次set操作时看是否是[a,b]覆盖区间,不是则查看是否此节点有set(1)或set(0)的标志,如果有的话,需要
把这个set标志pushdown到L(t),R(t),然后再把[a,b]的取反标志f,pushdown下去,然后递归查找左右子树。
如果【a,b]是覆盖区间,那么直接设置set标志,并把取反标志设0,(因为此时下边区间是否取反已经无所谓了)
2.每次update取反时差不多,需要把有set标志的先pushdown然后pushdown取反标志。
因为一个节点如果同时有两个标志时,一定表示这个节点先进行了set然后才取反,所以pushdown的时候先push set标志然后是取反标志。
假设是标志设置顺序是先取反,那么后来的set标志时后吧f清零(每set一个覆盖区间,相应区间的f=0)所以只可能是先set,再取反
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<cmath>#define L(x) (x<<1)#define R(x) (x<<1|1)#define MAX 100010using namespace std;void Swap(int t);void upwb(int t);void uplen(int t);void setdown(int t);void setdowncover(int t);void build(int t,int l, int r);void set(int t,int l,int r,int val);int querysum(int t,int l,int r);void update(int t,int l,int r);int queryblen(int t,int l,int r);struct node{ int l,r; int wr,wl,br,bl; int wlen,blen; int cover; int sum; bool f;}a[MAX*3];int number[MAX];int main(){ int t,m,n,i,l,r,p; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(i=0;i<n;i++) { scanf("%d",&number[i]); } build(1,0,n-1); for(i=0;i<m;i++) { scanf("%d%d%d",&p,&l,&r); switch(p) { case 0:; case 1:set(1,l,r,p);break; case 2:update(1,l,r);break; case 3:printf("%d\n",querysum(1,l,r));break; case 4:printf("%d\n",queryblen(1,l,r)); } } }}void Swap(int t){ swap(a[t].wlen,a[t].blen); swap(a[t].wl,a[t].bl); swap(a[t].wr,a[t].br); a[t].sum=a[t].r-a[t].l+1-a[t].sum;}void upwb(int t){ int ll=a[L(t)].r-a[L(t)].l+1; a[t].wl=a[L(t)].wl+(a[L(t)].wl==ll?a[R(t)].wl:0); a[t].bl=a[L(t)].bl+(a[L(t)].bl==ll?a[R(t)].bl:0); ll=a[R(t)].r-a[R(t)].l+1; a[t].wr=a[R(t)].wr+(a[R(t)].wr==ll?a[L(t)].wr:0); a[t].br=a[R(t)].br+(a[R(t)].br==ll?a[L(t)].br:0); a[t].wlen=max(max(a[L(t)].wlen,a[R(t)].wlen),a[L(t)].wr+a[R(t)].wl); a[t].blen=max(max(a[L(t)].blen,a[R(t)].blen),a[L(t)].br+a[R(t)].bl);}void uplen(int t){ if(a[t].cover>0) { a[t].sum=a[t].r-a[t].l+1; a[t].wlen=a[t].wl=a[t].wr=0; a[t].blen=a[t].bl=a[t].br=a[t].sum; return; } if(a[t].cover==0) { a[t].sum=0; a[t].wlen=a[t].r-a[t].l+1; a[t].wr=a[t].wl=a[t].wlen; a[t].blen=a[t].br=a[t].bl=0; return ; } a[t].sum=a[L(t)].sum+a[R(t)].sum; upwb(t);}void setdown(int t){ if(a[t].f) { a[L(t)].f=!a[L(t)].f; a[R(t)].f=!a[R(t)].f; a[t].f=!a[t].f; Swap(L(t)); Swap(R(t)); }}void setdowncover(int t){ a[L(t)].cover=a[t].cover; a[R(t)].cover=a[t].cover; a[t].cover=-1; uplen(L(t)); uplen(R(t)); a[L(t)].f=0; a[R(t)].f=0;}void build(int t,int l, int r){ a[t].l=l; a[t].r=r; a[t].f=0; a[t].cover=-1; if(l==r) { a[t].blen=number[l]; a[t].wlen=1-a[t].blen; a[t].wr=a[t].wl=a[t].wlen; a[t].bl=a[t].br=a[t].blen; a[t].sum=number[l]; return ; } int mid=(l+r)>>1; build(L(t),l,mid); build(R(t),mid+1,r); uplen(t);}void set(int t,int l,int r,int val){ if(l<=a[t].l&&a[t].r<=r) { a[t].cover=val; a[t].f=0; uplen(t); return ; } if(a[t].cover!=-1) { setdowncover(t); a[L(t)].f=0; a[R(t)].f=0; } setdown(t); int mid=(a[t].l+a[t].r)>>1; if(l<=mid) set(L(t),l,r,val); if(r>mid) set(R(t),l,r,val); uplen(t);}int querysum(int t,int l,int r){ if(l<=a[t].l&&a[t].r<=r) { return a[t].sum; } if(a[t].cover!=-1) { setdowncover(t); } setdown(t); int mid=(a[t].l+a[t].r)>>1; int ans=0; if (l<=mid) ans+=querysum(L(t),l,r); if(r>mid) ans+=querysum(R(t),l,r); uplen(t); return ans;}void update(int t,int l,int r){ if(l<=a[t].l&&a[t].r<=r) { a[t].f=!a[t].f; Swap(t); return ; } if(a[t].cover!=-1) { setdowncover(t); } setdown(t); int mid=(a[t].l+a[t].r)>>1; if(l<=mid) update(L(t),l,r); if(r>mid) update(R(t),l,r); uplen(t);}int queryblen(int t,int l,int r){ if(l<=a[t].l&&a[t].r<=r) { return a[t].blen; } if(a[t].cover!=-1) { setdowncover(t); } setdown(t); int mid=(a[t].l+a[t].r)>>1; int ans=0; int p=0; int q=0; if(l<=mid) { ans=max(ans,queryblen(L(t),l,r)); if(r>=a[L(t)].r) p=min(a[L(t)].br,a[L(t)].r-l+1); } if(r>mid) { ans=max(ans,queryblen(R(t),l,r)); if(l<=a[R(t)].l) q=min(a[R(t)].bl,r-a[R(t)].l+1); } ans=max(ans,p+q); uplen(t); return ans;}
- hdu3397
- hdu3397
- hdu3397
- hdu3397 线段树综合
- HDU3397 Sequence Operation
- HDU3397--Sequence operation
- hdu3397 线段树
- HDU3397 Sequence operation
- hdu3397----Sequence operation
- hdu3397 Sequence operation
- hdu3397 Sequence operation
- HDU3397-Sequence operation
- 线段树区间维护hdu3397
- HDU3397区间合并 延迟标记
- HDU3397 Sequence operation(线段树)
- hdu3397 Sequence operation 线段树区间合并
- hdu3397 Sequence operation(线段树成段更新)
- HDU3397:Sequence operation(线段树区间合并)
- ios开发学习--日历(Calendar)效果源码分享--系列教程
- HOJ 1995 Venn Diagram
- makefile介绍
- 通过本机硬盘重装系统 (支持Win8/Win7等)新途径-NT6 HDD Installer使用教程
- 了解并解决代码签名问题
- hdu3397
- php删除文件夹及其文件夹下所有文件
- POJ 1565 Skew数
- c#无客户端连接ORACLE 10G
- xkjcf漏洞系列----robots.txt泄露了天机
- mfc 中画线的几种方法,画刷
- 这个程序的结果究竟是多少呢?
- PS中如何批量修改图片大小
- 2012.11.27