bzoj 1858: [Scoi2010]序列操作 线段树
2017-02-13 19:48
295 查看
题意
lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全变成1 2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0 3 a b 询问[a, b]区间内总共有多少个1 4 a b 询问[a, b]区间内最多有多少个连续的1 对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?n,m<=100000
分析
线段树直接上即可。代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define N 100005 using namespace std; int n,m,tot,a ,root; struct tree{int l,r,rev,tag,l1,l0,r1,r0,sum,mx1,mx0;}t[N*4]; void updata(int d,int l,int r) { int mid=(l+r)/2,lenl=mid-l+1,lenr=r-mid; t[d].sum=t[t[d].l].sum+t[t[d].r].sum; t[d].l0=t[t[d].l].l0; if (t[t[d].l].l0==lenl) t[d].l0+=t[t[d].r].l0; t[d].l1=t[t[d].l].l1; if (t[t[d].l].l1==lenl) t[d].l1+=t[t[d].r].l1; t[d].r0=t[t[d].r].r0; if (t[t[d].r].r0==lenr) t[d].r0+=t[t[d].l].r0; t[d].r1=t[t[d].r].r1; if (t[t[d].r].r1==lenr) t[d].r1+=t[t[d].l].r1; t[d].mx0=max(t[t[d].l].mx0,max(t[t[d].r].mx0,t[t[d].l].r0+t[t[d].r].l0)); t[d].mx1=max(t[t[d].l].mx1,max(t[t[d].r].mx1,t[t[d].l].r1+t[t[d].r].l1)); } void pushdown(int d,int l,int r) { if (l==r) return; int mid=(l+r)/2; if (t[d].tag!=-1) { if (t[d].tag==1) { t[t[d].l].l0=t[t[d].l].r0=t[t[d].l].mx0=0; t[t[d].l].l1=t[t[d].l].r1=t[t[d].l].sum=t[t[d].l].mx1=mid-l+1; t[t[d].r].l0=t[t[d].r].r0=t[t[d].r].mx0=0; t[t[d].r].l1=t[t[d].r].r1=t[t[d].r].sum=t[t[d].r].mx1=r-mid; } else { t[t[d].l].l1=t[t[d].l].r1=t[t[d].l].mx1=t[t[d].l].sum=0; t[t[d].l].l0=t[t[d].l].r0=t[t[d].l].mx0=mid-l+1; t[t[d].r].l1=t[t[d].r].r1=t[t[d].r].mx1=t[t[d].r].sum=0; t[t[d].r].l0=t[t[d].r].r0=t[t[d].r].mx0=r-mid; } t[t[d].l].rev=t[t[d].r].rev=0; t[t[d].l].tag=t[t[d].r].tag=t[d].tag; t[d].tag=-1; } if (t[d].rev) { swap(t[t[d].l].mx0,t[t[d].l].mx1); swap(t[t[d].l].l0,t[t[d].l].l1); swap(t[t[d].l].r0,t[t[d].l].r1); t[t[d].l].sum=mid-l+1-t[t[d].l].sum; swap(t[t[d].r].mx0,t[t[d].r].mx1); swap(t[t[d].r].l0,t[t[d].r].l1); swap(t[t[d].r].r0,t[t[d].r].r1); t[t[d].r].sum=r-mid-t[t[d].r].sum; if (t[t[d].l].tag!=-1) t[t[d].l].tag^=1; else t[t[d].l].rev^=1; if (t[t[d].r].tag!=-1) t[t[d].r].tag^=1; else t[t[d].r].rev^=1; t[d].rev=0; } } void build(int &d,int l,int r) { d=++tot; t[d].tag=-1; if (l==r) { if (a[l]) t[d].mx1=t[d].sum=t[d].l1=t[d].r1=1; else t[d].mx0=t[d].l0=t[d].r0=1; return; } int mid=(l+r)/2; build(t[d].l,l,mid); build(t[d].r,mid+1,r); updata(d,l,r); } void fill(int d,int l,int r,int x,int y,int z) { pushdown(d,l,r); if (l==x&&r==y) { if (z==1) { t[d].l0=t[d].r0=t[d].mx0=0; t[d].l1=t[d].r1=t[d].sum=t[d].mx1=r-l+1; } else { t[d].l1=t[d].r1=t[d].mx1=t[d].sum=0; t[d].l0=t[d].r0=t[d].mx0=r-l+1; } t[d].tag=z; return; } int mid=(l+r)/2; if (y<=mid) fill(t[d].l,l,mid,x,y,z); else if (x>mid) fill(t[d].r,mid+1,r,x,y,z); else { fill(t[d].l,l,mid,x,mid,z); fill(t[d].r,mid+1,r,mid+1,y,z); } updata(d,l,r); } void rev(int d,int l,int r,int x,int y) { pushdown(d,l,r); if (l==x&&r==y) { swap(t[d].mx0,t[d].mx1); swap(t[d].l0,t[d].l1); swap(t[d].r0,t[d].r1); t[d].sum=r-l+1-t[d].sum; t[d].rev^=1; return; } int mid=(l+r)/2; if (y<=mid) rev(t[d].l,l,mid,x,y); else if (x>mid) rev(t[d].r,mid+1,r,x,y); else { rev(t[d].l,l,mid,x,mid); rev(t[d].r,mid+1,r,mid+1,y); } updata(d,l,r); } int query(int d,int l,int r,int x,int y,int op) { pushdown(d,l,r); if (l==x&&r==y) { if (op==1) return t[d].sum; else return t[d].mx1; } int mid=(l+r)/2; if (y<=mid) return query(t[d].l,l,mid,x,y,op); else if (x>mid) return query(t[d].r,mid+1,r,x,y,op); else { if (op==1) return query(t[d].l,l,mid,x,mid,op)+query(t[d].r,mid+1,r,mid+1,y,op); else return max(query(t[d].l,l,mid,x,mid,op),max(query(t[d].r,mid+1,r,mid+1,y,op),min(t[t[d].l].r1,mid-x+1)+min(t[t[d].r].l1,y-mid))); } } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); build(root,1,n); for (int i=1;i<=m;i++) { int op,l,r; scanf("%d%d%d",&op,&l,&r); l++;r++; if (op==0) fill(root,1,n,l,r,0); else if (op==1) fill(root,1,n,l,r,1); else if (op==2) rev(root,1,n,l,r); else if (op==3) printf("%d\n",query(root,1,n,l,r,1)); else printf("%d\n",query(root,1,n,l,r,2)); } return 0; }
相关文章推荐
- BZOJ 1858 [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 [线段树]
- [省选] [线段树] [BZOJ1858] [SCOI2010] 序列操作
- BZOJ_1858_[Scoi2010]序列操作_线段树
- [BZOJ 1858][Scoi2010]序列操作(线段树)
- BZOJ 1858 [Scoi2010]序列操作 线段树
- bzoj1858[Scoi2010]序列操作 线段树
- BZOJ 1858 SCOI2010 序列操作 线段树
- 【bzoj 1858】 [Scoi2010]序列操作 线段树
- 线段树 BZOJ1858 [Scoi2010]序列操作
- BZOJ 1858: [Scoi2010]序列操作( 线段树 )
- BZOJ 1858: [Scoi2010]序列操作 线段树
- BZOJ 1858 SCOI2010 序列操作 线段树
- BZOJ 1858: [Scoi2010]序列操作 线段树区间修改查询
- bzoj 1858: [Scoi2010]序列操作【线段树】
- 【BZOJ1858】[Scoi2010]序列操作【线段树】
- BZOJ 1858 [Scoi2010]序列操作 线段树
- 【BZOJ 1858】【SCOI 2010】序列操作【区间线段树】
- BZOJ 1858 [Scoi2010]序列操作 - 线段树