P2572 [SCOI2010] 序列操作 —— 线段树

题意

原题

给定一个0/1序列,初始全为零要求分别实现:

-区间赋值

-区间取反

-询问区间1的个数

-询问区间为1的最大子段和

分析

形式化地定义变量,我们记下区间的0/1个数,0/1最大字段和,赋值与取反标记。

赋值的标记优先级大于取反标记,取反直接把区间赋值标记,区间0/1个数和最大子段和交换。

不复杂的题面,要注意很多细节,耐心写总能过。

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+100;
struct segtree
{
    struct node
    {
        int val[2],l,r,siz;
        int tag[2],xo;
        int lsum[2],rsum[2],all[2];
        node()
        {
            val[0]=val[1]=0;
            l=r=siz=xo=0;
            tag[0]=tag[1]=0;
            lsum[0]=lsum[1]=rsum[0]=rsum[1]=0;
            all[0]=all[1]=0;
        }
    }s[N<<2];



    node ans;
    void pushup(node &nw,node &lc,node &rc)
    {
        nw.siz=lc.siz+rc.siz;
        for(int j=0;j<=1;++j)
        {
            nw.val[j]=lc.val[j]+rc.val[j];
            nw.lsum[j]=lc.lsum[j];
            nw.rsum[j]=rc.rsum[j];
            if(lc.val[j]==lc.siz)
                nw.lsum[j]=lc.siz+rc.lsum[j];
            if(rc.val[j]==rc.siz)
                nw.rsum[j]=rc.siz+lc.rsum[j];
            nw.all[j]=lc.rsum[j]+rc.lsum[j];
            nw.all[j]=max(max(lc.all[j],rc.all[j]),nw.all[j]);
            nw.all[j]=max(max(nw.lsum[j],nw.rsum[j]) , nw.all[j]);
        }
    }

    void build(int i,int l,int r,int g[])
    {
        s[i].l=l;
        s[i].r=r;
        s[i].siz=r-l+1;
        if(l==r)
        {
            s[i].lsum[g[l]]=s[i].rsum[g[l]]=1;
            s[i].all[g[l]]=s[i].val[g[l]]=1;
            return ;
        }
        int mid=(l+r)>>1;
        build(i<<1,l,mid,g);
        build(i<<1|1,mid+1,r,g);
        pushup(s[i],s[i<<1],s[i<<1|1]);
    }

    void pushtag1(int i)
    {
        s[i].xo^=1;
        swap(s[i].val[0],s[i].val[1]);
        swap(s[i].lsum[0],s[i].lsum[1]);
        swap(s[i].rsum[0],s[i].rsum[1]);
        swap(s[i].all[0],s[i].all[1]);
        swap(s[i].tag[0],s[i].tag[1]);
    }

    void pushtag2(int i,int z)
    {
        s[i].tag[z]=1;
        s[i].tag[z^1]=0;
        s[i].xo=0;
        s[i].val[z]=s[i].siz;
        s[i].val[z^1]=0;
        //s[i].all[z]=1; !!!!!
        s[i].all[z]=s[i].siz;
        s[i].all[z^1]=0;
        s[i].lsum[z]=s[i].rsum[z]=s[i].all[z]=s[i].siz;
        s[i].lsum[z^1]=s[i].rsum[z^1]=s[i].all[z^1]=0;
    }

    void pushdown(int i)
    {
        if(!s[i].xo && !s[i].tag[0] && !s[i].tag[1])
            return ;
        if(s[i].tag[0]==1)
        {
            pushtag2(i<<1,0);
            pushtag2(i<<1|1,0);
        }
        else if(s[i].tag[1]==1)
        {
            pushtag2(i<<1,1);
            pushtag2(i<<1|1,1);
        }
        else if(s[i].xo==1)
        {
            pushtag1(i<<1);
            pushtag1(i<<1|1);
        }
        s[i].xo=s[i].tag[0]=s[i].tag[1]=0;
    }

    void upd1(int i,int x,int y,int z)//turn to z
    {
        if(s[i].l>=x && s[i].r<=y)
        {
            pushtag2(i,z);
            return ;
        }
        pushdown(i);
        int mid=(s[i].l+s[i].r)>>1;
        if(x<=mid)
            upd1(i<<1,x,y,z);
        if(y>mid)
            upd1(i<<1|1,x,y,z);
        pushup(s[i],s[i<<1],s[i<<1|1]);
    }
    void upd2(int i,int x,int y)//swap 0,1
    {
        if(s[i].l>=x && s[i].r<=y)
        {
            pushtag1(i);
            return ;
        }
        pushdown(i);
        int mid=(s[i].l+s[i].r)>>1;
        if(x<=mid)
            upd2(i<<1,x,y);
        if(y>mid)
            upd2(i<<1|1,x,y);
        pushup(s[i],s[i<<1],s[i<<1|1]);
    }
    int que3(int i,int x,int y,int z)
    {
        if(s[i].l>=x && s[i].r<=y)
            return s[i].val[z];
        pushdown(i);
        int mid=(s[i].l+s[i].r)>>1,sum=0;
        if(x<=mid)
            sum+=que3(i<<1,x,y,z);
        if(y>mid)
            sum+=que3(i<<1|1,x,y,z);
        return sum;
    }
    void cl(node &nw)
    {
        nw.all[0]=nw.all[1]=0;
        nw.lsum[0]=nw.lsum[1]=0;
        nw.rsum[0]=nw.rsum[1]=0;
        nw.val[0]=nw.val[1]=0;
        nw.siz=0;
    }
    node que4(int i,int x,int y,int z)
    {
        if(s[i].l>=x && s[i].r<=y)
            return s[i];
        pushdown(i);
        int mid=(s[i].l+s[i].r)>>1;
        node emp,lc,rc;
        if(x<=mid)
            lc=que4(i<<1,x,y,z);
        if(y>mid)
            rc=que4(i<<1|1,x,y,z);
        pushup(emp,lc,rc);
        return emp;
    }
    int que5(int x,int y,int z)
    {
        ans=que4(1,x,y,z);
        return ans.all[z];
    }
}T;
int g[N],n,m;

void work()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
        scanf("%d",g+i);
    T.build(1,1,n,g);
    while(m--)
    {
        int opt,x,y;
        scanf("%d%d%d",&opt,&x,&y);
        ++x;++y;
        if(opt==0 || opt==1)
            T.upd1(1,x,y,opt);
        else if(opt==2)
            T.upd2(1,x,y);
        else
        {
            if(opt==3)
            {
                int ans=T.que3(1,x,y,1);
                printf("%d\n",ans);
            }
            else
            {
                int ans=T.que5(x,y,1);
                printf("%d\n",ans);
            }
        }
    }
}
int main()
{
    work();
    return 0;
}











posted @ 2025-01-05 21:53  Glowingfire  阅读(40)  评论(0)    收藏  举报