线段树求调

P2572 [SCOI2010] 序列操作

czy0407 @ 2024-04-12 11:45:05

#include<bits/stdc++.h>
#define ll long long
#define ls(u) u<<1
#define rs(u) u<<1|1
using namespace std;
const int N=1e5+10;
int n,m;
int a[N];
struct tree
{
    ll mark[N<<2],rev[N<<2],sum[2][N<<2],ans[2][N<<2],ml[2][N<<2],mr[2][N<<2],L[N<<2],R[N<<2];
    void pushup(ll u)
    {
        for(int i=0;i<=1;i++)
        {
            ans[i][u]=max(ans[i][ls(u)],ans[i][rs(u)]);
            sum[i][u]=sum[i][ls(u)]+sum[i][rs(u)];
            ml[i][u]=ml[i][ls(u)];
            mr[i][u]=mr[i][rs(u)];
            ans[i][u]=max(ans[i][u],mr[i][ls(u)]+ml[i][rs(u)]);
            if(sum[i][ls(u)]=R[ls(u)]-L[ls(u)]+1)ml[i][u]=max(ml[i][u],ml[i][ls(u)]+ml[i][rs(u)]);
            if(sum[i][rs(u)]=R[rs(u)]-L[rs(u)]+1)mr[i][u]=max(mr[i][u],mr[i][rs(u)]+mr[i][ls(u)]);
        }
    }
    void down(ll u)
    {
        int op=mark[u];
        if(op!=-1)
        {
            ans[op][u]=sum[op][u]=ml[op][u]=mr[op][u]=R[u]-L[u]+1;
            ans[!op][u]=sum[!op][u]=ml[!op][u]=mr[!op][u]=0;
            ans[op][ls(u)]=sum[op][ls(u)]=ml[op][ls(u)]=mr[op][ls(u)]=R[ls(u)]-L[ls(u)]+1;
            ans[!op][ls(u)]=sum[!op][ls(u)]=ml[!op][ls(u)]=mr[!op][ls(u)]=0;
            ans[op][rs(u)]=sum[op][rs(u)]=ml[op][rs(u)]=mr[op][rs(u)]=R[rs(u)]-L[rs(u)]+1;
            ans[!op][rs(u)]=sum[!op][rs(u)]=ml[!op][rs(u)]=mr[!op][rs(u)]=0;
            rev[ls(u)]=rev[rs(u)]=rev[u]=0;
            mark[ls(u)]=mark[rs(u)]=op;
            mark[u]=-1;
        }
        if(rev[u])
        {
            swap(sum[0][u],sum[1][u]);
            swap(ans[0][u],ans[1][u]);
            swap(ml[0][u],ml[1][u]);
            swap(mr[0][u],mr[1][u]);
            int u2=u;
            u=ls(u);
            swap(sum[0][u],sum[1][u]);
            swap(ans[0][u],ans[1][u]);
            swap(ml[0][u],ml[1][u]);
            swap(mr[0][u],mr[1][u]);
            u=rs(u2);
            swap(sum[0][u],sum[1][u]);
            swap(ans[0][u],ans[1][u]);
            swap(ml[0][u],ml[1][u]);
            swap(mr[0][u],mr[1][u]);
            u=u2;
            if(mark[ls(u)]!=-1)mark[ls(u)]^=1;
            else rev[ls(u)]^=1;
            if(mark[rs(u)]!=-1)mark[rs(u)]^=1;
            else rev[rs(u)]^=1;
            rev[u]=0;
        }
    }
    void build(ll u,ll l,ll r)
    {
        L[u]=l;
        R[u]=r;
        if(l==r)
        {
            sum[a[l]][u]=ml[a[l]][u]=mr[a[l]][u]=a[l];
            sum[!a[l]][u]=ml[!a[l]][u]=mr[!a[l]][u]=!a[l];
            return;
        }
        if(l<r)
        {
            int mid=(l+r)>>1;
            build(ls(u),l,mid);
            build(rs(u),mid+1,r);
            pushup(u);
        }
    }
    void up(ll u,ll l,ll r,ll L,ll R,ll k)
    {
        if(L>r||l>R)return;
        if(L<=l&&r<=R)
        {
            sum[k][u]=ml[k][u]=mr[k][u]=ans[k][u]=r-l+1;
            sum[!k][u]=ml[!k][u]=mr[!k][u]=ans[!k][u]=0;
            mark[u]=k;
        }
        else
        {
            if(l<r)
            {
                int mid=(l+r)>>1;
                down(u);
                if(L<=mid)up(ls(u),l,mid,L,R,k);
                if(R>mid)up(rs(u),mid+1,r,L,R,k);
                pushup(u);
            }
        }
    }
    void up2(ll u,ll l,ll r,ll L,ll R)
    {
        if(L>r||l>R)return;
        if(L<=l&&r<=R)
        {
            swap(sum[0][u],sum[1][u]);
            swap(ans[0][u],ans[1][u]);
            swap(ml[0][u],ml[1][u]);
            swap(mr[0][u],mr[1][u]);
            rev[u]=2;
        }
        else
        {
            if(l<r)
            {
                int mid=(l+r)>>1;
                down(u);
                if(L<=mid)up2(ls(u),l,mid,L,R);
                if(R>mid)up2(rs(u),mid+1,r,L,R);
                pushup(u);
            }
        }
    }
    ll query1(ll u,ll l,ll r,ll L,ll R)
    {
        if(L>r||l>R)return 0;
        if(L<=l&&r<=R)return sum[1][u];
        if(l<r)
        {
            ll mid=(l+r)>>1,ans=0;
            down(u);
            if(L<=mid)ans+=query1(ls(u),l,mid,L,R);
            if(R>=mid)ans+=query1(rs(u),mid+1,r,L,R);
            return ans;
        }
    }
    ll query2(ll u,ll l,ll r,ll L,ll R)
    {
        if(L>r||l>R)return 0;
        if(L<=l&&r<=R)return ans[1][u];
        if(l<r)
        {
            ll mid=(l+r)>>1,ans=0;
            down(u);
            if(L<=mid)ans=max(ans,query2(ls(u),l,mid,L,R));
            if(R>=mid)ans=max(ans,query2(rs(u),mid+1,r,L,R));
            return ans;
        }
    }
}tr;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    memset(tr.mark,-1,sizeof(tr.mark));
    for(int i=1;i<=n;i++)cin>>a[i];
    tr.build(1,1,n);
    while(m--)
    {
        ll k,l,r;
        cin>>k>>l>>r;
        if(k==0||k==1)tr.up(1,1,n,l,r,k);
        if(k==2)tr.up2(1,1,n,l,r);
        if(k==3)cout<<tr.query1(1,1,n,l,r)<<"\n";
        if(k==4)cout<<tr.query2(1,1,n,l,r)<<"\n";
    }
    return 0;
}

样例没过


by darkmonster @ 2024-04-18 15:58:48

down操作,清空rev的时候,把左右孩子清空就行,清空自己不对


|