您的位置:首页 > 其它

【SCOI2010】序列操作 线段树

2017-03-24 14:14 274 查看

题目描述

  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都需要给出回答,聪明的程序员们,你们能帮助他吗?

数据范围

1<=n, m<=100000

样例输入

10 10

0 0 0 1 1 0 1 0 1 1

1 0 2

3 0 5

2 2 2

4 0 4

0 3 6

2 3 7

4 2 8

1 0 5

0 5 6

3 3 9

样例输出

5

2

6

5

解题思路

维护一些属性与标记(什么属性什么标记就略了A.A)

注意rev应该是rev[x]^=1,而不是rev[x]=1

还有如果将一段区间改为了0或1,应该删掉rev标记

害我调了一中午QWQ

代码

#include <bits/stdc++.h>
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
struct node{
int L,r,Sum[2],MaxL[2],Maxr[2],Max[2],c1,c0,rev;
}Tree[400005];
int vl[100005];
int GetSize(int v){
return Tree[v].r-Tree[v].L+1;
}
void PushUp(int v,int op){
Tree[v].Sum[op]=Tree[2*v].Sum[op]+Tree[2*v+1].Sum[op];
Tree[v].MaxL[op]=Tree[2*v].MaxL[op]+(Tree[2*v].MaxL[op]==GetSize(2*v)?Tree[2*v+1].MaxL[op]:0);
Tree[v].Maxr[op]=Tree[2*v+1].Maxr[op]+(Tree[2*v+1].Maxr[op]==GetSize(2*v+1)?Tree[2*v].Maxr[op]:0);
Tree[v].Max[op]=max(Tree[2*v].Max[op],Tree[2*v+1].Max[op]);
Tree[v].Max[op]=max(Tree[v].MaxL[op],Tree[v].Max[op]);
Tree[v].Max[op]=max(Tree[v].Maxr[op],Tree[v].Max[op]);
Tree[v].Max[op]=max(Tree[2*v].Maxr[op]+Tree[2*v+1].MaxL[op],Tree[v].Max[op]);
}
int PushUp(int v){PushUp(v,0);PushUp(v,1);return 0;}
void PushDown(int v){
if(Tree[v].c1){
Tree[2*v].c0=0;
Tree[2*v].c1=1;
Tree[2*v].rev=0;
Tree[2*v].Max[0]=Tree[2*v].Sum[0]=Tree[2*v].MaxL[0]=Tree[2*v].Maxr[0]=0;
Tree[2*v].Max[1]=Tree[2*v].Sum[1]=Tree[2*v].MaxL[1]=Tree[2*v].Maxr[1]=GetSize(2*v);
Tree[2*v+1].c0=0;
Tree[2*v+1].c1=1;
Tree[2*v+1].rev=0;
Tree[2*v+1].Max[0]=Tree[2*v+1].Sum[0]=Tree[2*v+1].MaxL[0]=Tree[2*v+1].Maxr[0]=0;
Tree[2*v+1].Max[1]=Tree[2*v+1].Sum[1]=Tree[2*v+1].MaxL[1]=Tree[2*v+1].Maxr[1]=GetSize(2*v+1);
Tree[v].c1=0;
}
if(Tree[v].c0){
Tree[2*v].c1=0;
Tree[2*v].c0=1;
Tree[2*v].rev=0;
Tree[2*v].Max[1]=Tree[2*v].Sum[1]=Tree[2*v].MaxL[1]=Tree[2*v].Maxr[1]=0;
Tree[2*v].Max[0]=Tree[2*v].Sum[0]=Tree[2*v].MaxL[0]=Tree[2*v].Maxr[0]=GetSize(2*v);
Tree[2*v+1].c1=0;
Tree[2*v+1].c0=1;
Tree[2*v+1].rev=0;
Tree[2*v+1].Max[1]=Tree[2*v+1].Sum[1]=Tree[2*v+1].MaxL[1]=Tree[2*v+1].Maxr[1]=0;
Tree[2*v+1].Max[0]=Tree[2*v+1].Sum[0]=Tree[2*v+1].MaxL[0]=Tree[2*v+1].Maxr[0]=GetSize(2*v+1);
Tree[v].c0=0;
}
if(Tree[v].rev){
Tree[2*v].rev^=1;
Tree[2*v+1].rev^=1;
swap(Tree[2*v].Max[0],Tree[2*v].Max[1]);
swap(Tree[2*v].Sum[0],Tree[2*v].Sum[1]);
swap(Tree[2*v].MaxL[0],Tree[2*v].MaxL[1]);
swap(Tree[2*v].Maxr[0],Tree[2*v].Maxr[1]);
swap(Tree[2*v+1].Sum[0],Tree[2*v+1].Sum[1]);
swap(Tree[2*v+1].Max[0],Tree[2*v+1].Max[1]);
swap(Tree[2*v+1].MaxL[0],Tree[2*v+1].MaxL[1]);
swap(Tree[2*v+1].Maxr[0],Tree[2*v+1].Maxr[1]);
Tree[v].rev=0;
}
}
void Build(int v,int L,int r){
Tree[v]=(node){L,r,0,0,0,0,0,0,0,0,0,0,0};
if(L==r)return;
Build(2*v,L,(L+r)/2);
Build(2*v+1,(L+r)/2+1,r);
}
void Make_Same(int v,int L,int r,int op){
if(r<Tree[v].L||Tree[v].r<L)return;
if(L<=Tree[v].L&&Tree[v].r<=r){
if(op==0)Tree[v].c0=1,Tree[v].c1=0,Tree[v].rev=0;
if(op==1)Tree[v].c0=0,Tree[v].c1=1,Tree[v].rev=0;
Tree[v].Max[!op]=Tree[v].Sum[!op]=Tree[v].MaxL[!op]=Tree[v].Maxr[!op]=0;
Tree[v].Max[op]=Tree[v].Sum[op]=Tree[v].MaxL[op]=Tree[v].Maxr[op]=GetSize(v);
return;
}
PushDown(v);
Make_Same(2*v,L,r,op);
Make_Same(2*v+1,L,r,op);
PushUp(v);
}
void Rev(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return;
if(L<=Tree[v].L&&Tree[v].r<=r){
Tree[v].rev^=1;
swap(Tree[v].Max[0],Tree[v].Max[1]);
swap(Tree[v].Sum[0],Tree[v].Sum[1]);
swap(Tree[v].MaxL[0],Tree[v].MaxL[1]);
swap(Tree[v].Maxr[0],Tree[v].Maxr[1]);
return;
}
PushDown(v);
Rev(2*v,L,r);
Rev(2*v+1,L,r);
PushUp(v);
}
int AskTot(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return 0;
if(L<=Tree[v].L&&Tree[v].r<=r)
return Tree[v].Sum[1];
PushDown(v);
return AskTot(2*v,L,r)+AskTot(2*v+1,L,r);
}
int Ask(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return 0;
if(L<=Tree[v].L&&Tree[v].r<=r)
return Tree[v].Max[1];
PushDown(v);
int t=max(Ask(2*v,L,r),Ask(2*v+1,L,r));
t=max(t,min(Tree[2*v+1].L+Tree[2*v+1].MaxL[1]-1,r)-max(Tree[2*v].r-Tree[2*v].Maxr[1]+1,L)+1);
return t;
}
int main(){
int n=Getint(),m=Getint();
for(int i=1;i<=n;i++)vl[i]=Getint();
Build(1,1,n);
for(int i=1;i<=n;i++)Make_Same(1,i,i,vl[i]);
while(m--){
int op=Getint(),L=Getint()+1,r=Getint()+1;
if(op==0||op==1)Make_Same(1,L,r,op);
if(op==2)Rev(1,L,r);
if(op==3)cout<<AskTot(1,L,r)<<"\n";
if(op==4)cout<<Ask(1,L,r)<<"\n";
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: