BZOJ 1500 维修数列 Splay

SPLAY 模板题 

代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define splay_pool NIL
using namespace std;
const int max_size=500010;
const int INF=(1ll<<31)-2;
struct Node {
    int val,size;
    Node *lch,*rch,*fa;
    long long lsum,rsum,sum,msum;
    bool flag,rev;
    int setv;
    Node(){
        val=sum=flag=rev=size=0;
        msum=lsum=rsum=-INF>>5;
    }
    Node(int _val,Node *_lch,Node *_rch,Node *_fa)
    :val(_val),lch(_lch),rch(_rch),fa(_fa){
        size=1;
        lsum=rsum=sum=msum=_val;
        flag=rev=0;
    }
}splay_pool[max_size],*sp;
Node *pool[max_size];
struct splay_tree{
    int tot;
    Node *root,*head,*tail;
    splay_tree(){}
    void init(){
        tot=0;
        for(int i=1;i<max_size;i++)pool[tot++]=splay_pool+i;
        new(NIL)Node;
        sp=NIL;
        NIL->lch=NIL->rch=NIL->fa=NIL;
        head=new(pool[--tot])Node(-INF>>5,NIL,NIL,NIL);
        tail=new(pool[--tot])Node(-INF>>5,NIL,NIL,NIL);
        head->rch=tail;
        tail->fa=head;
        root=head;
        update(root);
    }
    void rever(Node *t){
        if(t==NIL)return;
        t->rev=!t->rev;
        swap(t->lch,t->rch);
        swap(t->lsum,t->rsum);
    }
    void set(Node *t,int val){
        if(t==NIL)return;
        t->flag=true;
        t->setv=val;
        t->val=val;
        t->sum=(long long)val*t->size;
        t->rsum=t->lsum=t->msum=max((long long)val,t->sum);
    }
    void update(Node *t){
        if(t==NIL)return;
        t->size=t->lch->size+t->rch->size+1;
        t->sum=t->val+t->rch->sum+t->lch->sum;
        t->msum=max(max(t->lch->msum,t->rch->msum),max(max(t->lch->rsum+t->val,t->rch->lsum+t->val),max((long long)t->val,t->rch->lsum+t->val+t->lch->rsum)));
        t->lsum=max(max(t->lch->lsum,t->lch->sum+t->val),t->lch->sum+t->val+t->rch->lsum);
        t->rsum=max(max(t->rch->rsum,t->rch->sum+t->val),t->rch->sum+t->val+t->lch->rsum);
        return ;
    }
    void pushdown(Node *t){
        if(t==NIL)return ;
        if(t->flag){
            set(t->lch,t->setv);
            set(t->rch,t->setv);
            t->flag=false;
        }
        if(t->rev){
            rever(t->lch);
            rever(t->rch);
            t->rev=false;
        }
    }
    void zig(Node *t){
        Node *f=t->fa,*c=t->rch;
        if(t->fa==root)root=t;
        else (f->fa->lch==f?f->fa->lch:f->fa->rch)=t;
        t->fa=f->fa,t->rch=f,f->lch=c,f->fa=t,c->fa=f;
        update(f),update(t);
    }
    void zag(Node *t){
        Node *f=t->fa,*c=t->lch;
        if(t->fa==root)root=t;
        else (f->fa->lch==f?f->fa->lch:f->fa->rch)=t;
        t->fa=f->fa,t->lch=f,f->rch=c,f->fa=t,c->fa=f;
        update(f),update(t);
    }
    void splay(Node *&root,Node *t){
        pushdown(t);
        while(t!=root){
            if(t->fa==root){
                if(t->fa->lch==t)zig(t);
                else zag(t);
            }
            else {
                if(t->fa->fa->lch==t->fa){
                    if(t->fa->lch==t)zig(t->fa),zig(t);
                    else zag(t),zig(t);
                }
                else {
                    if(t->fa->lch==t)zig(t),zag(t);
                    else zag(t->fa),zag(t);
                }
            }
        }
    }
    void select(Node *&root,int k){
        Node *t=root;
        while(true){
            pushdown(t);
            if(t->lch->size+1==k){
                splay(root,t);
                return;
            }
            if(t->lch->size>=k){
                t=t->lch;
            }
            else {
                k-=t->lch->size+1;
                t=t->rch;
            }
        }
    }
    void build(int l,int r,int a[],Node *&t,Node *fa){
        if(l>r)return;
        int mid=(l+r)>>1;
        t=new(pool[--tot])Node(a[mid],NIL,NIL,fa);
        build(l,mid-1,a,t->lch,t);
        build(mid+1,r,a,t->rch,t);
        update(t);
    }
    void insert(int pos,int a[],int len){
        select(root,pos+1);
        select(root->rch,1);
        build(1,len,a,root->rch->lch,root->rch);
        update(root->rch);
        update(root);
    }
    void dele(int pos,int tot){
        select(root,pos);
        select(root->rch,tot+1);
        erase(root->rch->lch);
        root->rch->lch=NIL;
        update(root->rch);
        update(root);
    }
    void modify(int pos,int tot,int val){
        select(root,pos);
        select(root->rch,tot+1);
        set(root->rch->lch,val);
        update(root->rch);
        update(root);
    }
    void reverse(int pos,int tot){
        select(root,pos);
        select(root->rch,tot+1);
        rever(root->rch->lch);
        update(root->rch);
        update(root);
    }
    int quarry(int pos,int tot){
        select(root,pos);
        select(root->rch,tot+1);
        return root->rch->lch->sum;
    }
    int max_sum(){
        return root->msum;
    }
    void erase(Node *t){
        if(t==NIL)return;
        erase(t->lch);
        erase(t->rch);
        pool[tot++]=t;
    }
    void dfs(Node *t){
        if(t==NIL)return;
        pushdown(t);
        dfs(t->lch);
        printf("%d\t",t->val);
        dfs(t->rch);
    }
    int size(){
        return root->size-2;
    }

}T;
const int maxn=500010;
int data[maxn];
int main(){
    int n,m;
//    freopen("sequence10.in","r",stdin);
//    freopen("sequence10.out","w",stdout);
    while(~scanf("%d%d",&n,&m)){
        T.init();
        for(int i=1;i<=n;i++){
            scanf("%d",&data[i]);
        }
        T.insert(0,data,n);
        char flag[100];
        int pos,len;
        int l,r;
        for(int i=0;i<m;i++){
            scanf("%s",flag);
            if(flag[0]=='G'){
                scanf("%d%d",&pos,&len);
                printf("%d\n",T.quarry(pos,len));
            }
            else if(flag[0]=='M'&&flag[3]=='-'){
                printf("%d\n",T.max_sum());
            }
            else if(flag[0]=='I'){

                scanf("%d%d",&pos,&len);
                for(int i=1;i<=len;i++){
                    scanf("%d",data+i);
                }
                T.insert(pos,data,len);
            }
            else if(flag[0]=='D'){
                scanf("%d%d",&pos,&len);
                T.dele(pos,len);
            }
            else if(flag[0]=='M'){
                int val;
                scanf("%d%d%d",&pos,&len,&val);
                T.modify(pos,len,val);
            }
            else {
                 scanf("%d%d",&pos,&len);
                 if(pos+len-1>T.size())
                    len=T.size()+1-pos;
                 T.reverse(pos,len);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值