线段树 HDU 3397(真)
Posted HelloWorld!--By-MJY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树 HDU 3397(真)相关的知识,希望对你有一定的参考价值。
5 种操作 0 1 然后 异或 似乎这种2个更新的先后每次都搞不清
覆盖有覆盖就可以不异或
也不知道为什么
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 100010 struct node { int l,r,ls,rs,ms; // 左边连续的1 右边 最多 int lz,rz,mz; // 0 int XOR,cov; // 异或 lazy int sum; //和 }x[MAXN<<3]; int z[MAXN]; void makexor(int a)//0 1 交换 { swap(x[a].ls,x[a].lz); swap(x[a].rs,x[a].rz); swap(x[a].ms,x[a].mz); x[a].sum=x[a].r-x[a].l+1-x[a].sum; } void push_up(int a) { int len=x[a].r-x[a].l+1; x[a].ls=x[a<<1].ls; x[a].rs=x[a<<1|1].rs; x[a].ms=max(x[a<<1].ms,x[a<<1|1].ms); if(x[a].ls==(len+1)>>1) //这边就是普通的区间合并 x[a].ls+=x[a<<1|1].ls; if(x[a].rs==len>>1) x[a].rs+=x[a<<1].rs; int mid=(x[a].r+x[a].l)>>1; // if(z[mid]==z[mid+1]&&z[mid]==1) //一开始这里一直错 其实后面更新了 不用考虑这个 x[a].ms=max(x[a].ms,x[a<<1].rs+x[a<<1|1].ls); x[a].lz=x[a<<1].lz; x[a].rz=x[a<<1|1].rz; x[a].mz=max(x[a<<1].mz,x[a<<1|1].mz); if(x[a].lz==(len+1)>>1) x[a].lz+=x[a<<1|1].lz; if(x[a].rz==len>>1) x[a].rz+=x[a<<1].rz; x[a].mz=max(x[a].mz,x[a<<1].rz+x[a<<1|1].lz); x[a].sum=x[a<<1].sum+x[a<<1|1].sum; } void push_down(int a) { if(x[a].cov!=-1) { int l=x[a].l; int r=x[a].r; int len=r-l+1; x[a<<1].cov=x[a<<1|1].cov=x[a].cov; x[a<<1].XOR=x[a<<1|1].XOR=0; x[a<<1].ls=x[a<<1].rs=x[a<<1].ms=x[a].cov?(len+1)>>1:0; x[a<<1].lz=x[a<<1].rz=x[a<<1].mz=x[a].cov?0:(len+1)>>1; x[a<<1].sum=x[a].cov?(len+1)>>1:0; x[a<<1|1].ls=x[a<<1|1].rs=x[a<<1|1].ms=x[a].cov?len>>1:0; x[a<<1|1].lz=x[a<<1|1].rz=x[a<<1|1].mz=x[a].cov?0:len>>1; x[a<<1|1].sum=x[a].cov?len>>1:0; x[a].cov=-1; } if(x[a].XOR) { x[a].XOR=0; x[a<<1].XOR^=1; x[a<<1|1].XOR^=1; makexor(a<<1); makexor(a<<1|1); } } void Build(int l,int r,int a) { x[a].l=l; x[a].r=r; x[a].XOR=0; x[a].cov=-1; if(l==r) { x[a].ls=x[a].rs=x[a].ms=(z[l]==1); x[a].lz=x[a].rz=x[a].mz=(z[l]==0); x[a].sum=z[l]; x[a].cov=z[l]; return ; } int mid=(l+r)>>1; Build(l,mid,a<<1); Build(mid+1,r,a<<1|1); push_up(a); } void update(int l,int r,int a1,int b1,int w,int a) { push_down(a); if(a1<=l&&r<=b1) { if(w<2) { int len=r-l+1; x[a].cov=w; x[a].ls=x[a].rs=x[a].ms=w?len:0; x[a].lz=x[a].rz=x[a].mz=w?0:len; x[a].sum=w?len:0; x[a].XOR=0; } else { x[a].XOR=1; makexor(a); } return ; } int mid=(l+r)>>1; if(a1<=mid) update(l,mid,a1,b1,w,a<<1); if(b1>mid) update(mid+1,r,a1,b1,w,a<<1|1); push_up(a); } int query_sum(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return x[rt].sum; } push_down(rt); int m=(l+r)>>1; int ans=0; if(L<=m) ans+=query_sum(L,R,l,m,rt<<1); if(m<R) ans+=query_sum(L,R,m+1,r,rt<<1|1); return ans; } int query_len(int L,int R,int l,int r,int rt) { push_down(rt); if(L<=l&&r<=R) { return x[rt].ms; } int m=(l+r)>>1; int ans=0; if(L<=m) ans=max(ans,query_len(L,R,l,m,rt<<1)); if(m<R) ans=max(ans,query_len(L,R,m+1,r,rt<<1|1)); return max(ans,min(m-L+1,x[rt<<1].rs)+min(R-m,x[rt<<1|1].ls)); } int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&z[i]); Build(1,n,1); while(m--) { int op,a,b; scanf("%d%d%d",&op,&a,&b); a++; b++; if(op<=2) update(1,n,a,b,op,1); else if(op==3) printf("%d\n",query_sum(a,b,1,n,1)); else printf("%d\n",query_len(a,b,1,n,1)); } } return 0; }
以上是关于线段树 HDU 3397(真)的主要内容,如果未能解决你的问题,请参考以下文章
hdu-3397 Sequence operation 线段树多种标记
hdu 3397 Sequence operation (线段树 区间合并 多重标记)
HDU 3397 Sequence operation 多标记线段树