您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: