【SCOI2010】序列操作 线段树

来源:互联网 发布:ipad上的淘宝怎么横屏 编辑:程序博客网 时间:2024/06/07 02:35

题目描述

  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;}
1 0
原创粉丝点击