treap-[NOI2005]维护数列

swap的标记要注意,打标记时先要更新根节点

#include<bits/stdc++.h>
using namespace std;
const int MAXA=4050000;
const int MAXN=5e8;
int val[MAXA],s[MAXA][2],su[MAXA][2],sum[MAXA],ans[MAXA],vflag[MAXA],tag[MAXA],siz[MAXA];
void update(int x){
    if(x==0) return ;
    siz[x]=siz[s[x][0]]+siz[s[x][1]]+1;
    sum[x]=val[x]+sum[s[x][0]]+sum[s[x][1]];
    su[x][0]=max(su[s[x][1]][0],sum[s[x][1]]+val[x]+max(0,su[s[x][0]][0]));
    su[x][1]=max(su[s[x][0]][1],sum[s[x][0]]+val[x]+max(0,su[s[x][1]][1]));
    ans[x]=max(max(ans[s[x][0]],ans[s[x][1]]),max(su[s[x][0]][0],0)+val[x]+max(su[s[x][1]][1],0));
}
void changevflag(int x,int y){
    if(!x) return ;
    vflag[x]=y;
    sum[x]=siz[x]*y;
    val[x]=y;
    if(y>0) su[x][0]=su[x][1]=ans[x]=sum[x];
    else su[x][0]=su[x][1]=ans[x]=y;
}
void tagp(int x){
    swap(s[x][0],s[x][1]);
    swap(su[x][0],su[x][1]);
}
void pushdown(int x){
    if(vflag[x]!=MAXN){
    changevflag(s[x][0],vflag[x]);
    changevflag(s[x][1],vflag[x]);
    vflag[x]=MAXN;
    }
    if(tag[x]){
    if(s[x][0]) tag[s[x][0]]^=1,tagp(s[x][0]);
    if(s[x][1]) tag[s[x][1]]^=1,tagp(s[x][1]);
    tag[x]=0;
    }
}
void make(int &n,int l,int r){
    if(l>r) return ;
    if(l==r){
    n=l;
    update(n);
    return;
    }
    n=(l+r)>>1;
    make(s[n][0],l,n-1);make(s[n][1],n+1,r);
    update(n);
}
int merge(int root1,int root2){
    if(!(root1+root2)) return 0;
    if(rand()%(siz[root1]+siz[root2])<siz[root1]){
    pushdown(root1);
    s[root1][1]=merge(s[root1][1],root2);
    update(root1);
    return root1;
    }else{
    pushdown(root2);
    s[root2][0]=merge(root1,s[root2][0]);
    update(root2);
    return root2;
    }
}
pair<int,int> spilt(int root,int cut){
    pushdown(root);
    if(cut==0) return make_pair(0,root);
    if(cut<=siz[s[root][0]]){
    pair<int,int> nxt=spilt(s[root][0],cut);
    s[root][0]=nxt.second;
    update(root);
    return make_pair(nxt.first,root);
    }
    cut-=siz[s[root][0]]+1;
    if(cut==0){
    int y=s[root][1];
    s[root][1]=0;
    update(root);
    return make_pair(root,y);
    }
    pair<int,int> nxt=spilt(s[root][1],cut);
    s[root][1]=nxt.first;
    update(root);
    return make_pair(root,nxt.second);
}
void printt(int x){
    if(!x) return ;
    pushdown(x);
    printt(s[x][0]);
    printf("%d ",val[x]);
    printt(s[x][1]);
}
void print(int x){
    if(!x) return ;
    pushdown(x);
    printf("%d %d %d %d %d\n",val[x],val[s[x][0]],val[s[x][1]],sum[x],ans[x]);
    print(s[x][0]);print(s[x][1]);
}
int main(){
    char ss[1000];
    int x,m,n,t,y,root;
    siz[0]=0; sum[0]=0; su[0][0]=su[0][1]=ans[0]=-MAXN-1;
    scanf("%d%d",&n,&t);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=0;i<=n;i++) vflag[i]=MAXN;
    make(root,1,n);
    //print(root);
    //printf("\n");
    while(t--){
    scanf("%s",ss);
    if(ss[2]=='S'){
        scanf("%d",&x);
        int ro;
        pair<int,int> ro1=spilt(root,x);
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        scanf("%d",&val[i+n]),vflag[i+n]=MAXN;
        make(ro,n+1,n+m);
        n+=m;
        root=merge(merge(ro1.first,ro),ro1.second);
    }
    if(ss[2]=='L'){
        scanf("%d%d",&x,&m);
        pair<int,int>ro1=spilt(root,x-1);
        pair<int,int>ro2=spilt(ro1.second,m);
        root=merge(ro1.first,ro2.second);
        //printt(root);
        //printf("\n");
    }
    if(ss[2]=='K'){
        scanf("%d%d%d",&x,&m,&y);
        pair<int,int>ro1=spilt(root,x-1);
        pair<int,int>ro2=spilt(ro1.second,m);
        changevflag(ro2.first,y);
        root=merge(merge(ro1.first,ro2.first),ro2.second);
    }
    if(ss[2]=='V'){
        scanf("%d%d",&x,&m);
        pair<int,int> ro1=spilt(root,x-1);
        pair<int,int>ro2=spilt(ro1.second,m);
        //printt(ro2.first);
        //printf("\n");
        tag[ro2.first]^=1;
        //swap(su[ro2.first][0],su[ro2.first][1]);
        //swap(s[ro2.first][0],s[ro2.first][1]);
        tagp(ro2.first);
        //printt(ro2.first);
        //printf("\n");
        root=merge(merge(ro1.first,ro2.first),ro2.second);
        //printt(root);
        //printf("\n");
    }
    if(ss[2]=='T'){
        scanf("%d%d",&x,&m);
        pair<int,int> ro1=spilt(root,x-1);
        pair<int,int>ro2=spilt(ro1.second,m);
        printf("%d\n",sum[ro2.first]);
        root=merge(merge(ro1.first,ro2.first),ro2.second);
    }
    if(ss[2]=='X'){
        printf("%d\n",ans[root]);
    }
    }
}

转载于:https://www.cnblogs.com/ac_forever/p/11185187.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值