[SCOI2010]序列操作

Posted ah2002

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SCOI2010]序列操作相关的知识,希望对你有一定的参考价值。

操作0、1:区间赋值

操作2:区间异或

操作3:区间求和

操作4:区间最长连续段

我们用线段树打lazy标记的方式维护:某段区间从左向右和从右向左延伸的0和1的长度、某段区间内0和1的最长长度、区间和。

然后分类讨论pushdown与pushup即可

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;

const int MAXN=1<<17;

int n,m;
int a[MAXN];
int lef[2][MAXN<<1],rig[2][MAXN<<1],mx[2][MAXN<<1];
int sm[MAXN<<1],tag[MAXN<<1],chg[MAXN<<1];

inline int read()
{
    int x=0;char ch=getchar();
    while(ch<‘0‘||‘9‘<ch) ch=getchar();
    while(‘0‘<=ch&&ch<=‘9‘) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x;
}

inline void pushup(int k,int l,int r)
{
    if(l==r) return;
    int i=k<<1,mid=l+r>>1;
    lef[0][k]=lef[0][i]==mid-l+1?lef[0][i]+lef[0][i|1]:lef[0][i];
    lef[1][k]=lef[1][i]==mid-l+1?lef[1][i]+lef[1][i|1]:lef[1][i];
    rig[0][k]=rig[0][i|1]==r-mid?rig[0][i|1]+rig[0][i]:rig[0][i|1];
    rig[1][k]=rig[1][i|1]==r-mid?rig[1][i|1]+rig[1][i]:rig[1][i|1];
    mx[0][k]=max(rig[0][i]+lef[0][i|1],max(mx[0][i],mx[0][i|1]));
    mx[1][k]=max(rig[1][i]+lef[1][i|1],max(mx[1][i],mx[1][i|1]));
    sm[k]=sm[i]+sm[i|1];
    return;
}

void build(int k,int l,int r)
{
    chg[k]=-1;
    if(l==r){
        if(a[l]) sm[k]=1;
        lef[a[l]][k]=rig[a[l]][k]=mx[a[l]][k]=1;
        return;
    }int i=k<<1,mid=l+r>>1;
    build(i,l,mid);build(i|1,mid+1,r);
    pushup(k,l,r);
    return;
}

void pushdown(int k,int l,int r)
{
    if(l==r||(!tag[k]&&chg[k]==-1)) return;
    int i=k<<1,mid=l+r>>1;
    if(tag[k]){
        if(chg[i]!=-1) chg[i]^=1;
        if(chg[i|1]!=-1) chg[i|1]^=1;
        tag[i]^=1;tag[i|1]^=1;
        sm[i]=mid-l+1-sm[i];sm[i|1]=r-mid-sm[i|1];
        swap(lef[0][i],lef[1][i]),swap(rig[0][i],rig[1][i]),swap(mx[0][i],mx[1][i]);
        swap(lef[0][i|1],lef[1][i|1]),swap(rig[0][i|1],rig[1][i|1]),swap(mx[0][i|1],mx[1][i|1]);
        tag[k]=0;
    }if(chg[k]!=-1){
        tag[i]=tag[i|1]=0;chg[i]=chg[i|1]=chg[k];
        sm[i]=chg[k]?mid-l+1:0;sm[i|1]=chg[k]?r-mid:0;
        lef[chg[k]][i]=rig[chg[k]][i]=mx[chg[k]][i]=mid-l+1;
        lef[chg[k]^1][i]=rig[chg[k]^1][i]=mx[chg[k]^1][i]=0;
        lef[chg[k]][i|1]=rig[chg[k]][i|1]=mx[chg[k]][i|1]=r-mid;
        lef[chg[k]^1][i|1]=rig[chg[k]^1][i|1]=mx[chg[k]^1][i|1]=0;
        chg[k]=-1;
    }return;
}

void cchg(int k,int l,int r,int le,int ri,int v)
{
    pushdown(k,l,r);
    if(le<=l&&r<=ri){
        sm[k]=v?r-l+1:0;
        lef[v][k]=rig[v][k]=mx[v][k]=r-l+1;
        lef[v^1][k]=rig[v^1][k]=mx[v^1][k]=0;
        chg[k]=v;
        return;
    }int i=k<<1,mid=l+r>>1;
    if(le<=mid) cchg(i,l,mid,le,ri,v);
    if(mid<ri) cchg(i|1,mid+1,r,le,ri,v);
    pushup(k,l,r);
    return;
}

void ctag(int k,int l,int r,int le,int ri)
{
    pushdown(k,l,r);
    if(le<=l&&r<=ri){
        tag[k]=1;
        sm[k]=r-l+1-sm[k];
        swap(lef[0][k],lef[1][k]);
        swap(rig[0][k],rig[1][k]);
        swap(mx[0][k],mx[1][k]);
        return;
    }int i=k<<1,mid=l+r>>1;
    if(le<=mid) ctag(i,l,mid,le,ri);
    if(mid<ri) ctag(i|1,mid+1,r,le,ri);
    pushup(k,l,r);
    return;
}

int cask1(int k,int l,int r,int le,int ri)
{
    pushdown(k,l,r);pushup(k,l,r);
    if(le<=l&&r<=ri) return sm[k];
    int i=k<<1,mid=l+r>>1,sum=0;
    if(le<=mid) sum+=cask1(i,l,mid,le,ri);
    if(mid<ri) sum+=cask1(i|1,mid+1,r,le,ri);
    return sum;
}

int cask2(int k,int l,int r,int le,int ri)
{
    pushdown(k,l,r);pushup(k,l,r);
    if(le<=l&&r<=ri) return mx[1][k];
    int i=k<<1,mid=l+r>>1,mxx=0;
    if(le<=mid&&mid<ri) mxx=max(max(cask2(i,l,mid,le,ri),cask2(i|1,mid+1,r,le,ri)),min(mid-le+1,rig[1][i])+min(ri-mid,lef[1][i|1]));
    else if(le<=mid) mxx=cask2(i,l,mid,le,ri);
    else if(mid<ri) mxx=cask2(i|1,mid+1,r,le,ri);
    return mxx;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) a[i]=read();
    build(1,1,n);
    while(m--){
        int p=read(),l=read()+1,r=read()+1;
        if(p==0) cchg(1,1,n,l,r,0);
        else if(p==1) cchg(1,1,n,l,r,1);
        else if(p==2) ctag(1,1,n,l,r);
        else if(p==3) printf("%d
",cask1(1,1,n,l,r));
        else printf("%d
",cask2(1,1,n,l,r));
    }return 0;
}

以上是关于[SCOI2010]序列操作的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 1858: [Scoi2010]序列操作

P2572 [SCOI2010]序列操作

[SCOI2010]序列操作

[SCOI2010]序列操作

[SCOI2010]序列操作

bzoj1858 [Scoi2010]序列操作