【SCOI2010】序列操作 线段树

题目描述

  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;
}

转载于:https://www.cnblogs.com/Cedric341561/p/6811011.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值