[BZOJ1500][NOI2005]维修数列

25 篇文章 0 订阅
9 篇文章 0 订阅

原题地址

Splay 练手题(本来块链能过我非要作死用Splay结果调成狗OLZ
写的又慢又长简直不能看OLZ

AC code:

#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=1<<29;
int n,m,cnt;

struct nod{
    int  v,tot,sum,lm,mm,rm,c;
    bool tc,tr;
    nod  *ch[2],*pr;
}*NIL;

struct Splay{
    nod *root;

    Splay(){
        root=NIL=new nod;
        NIL->sum=NIL->tot=0;
        NIL->lm=NIL->mm=NIL->rm=-INF;
    }

    void clear(nod *p){
        if(p==NIL) return ;
        if(p->tc){
            p->v=p->c;p->sum=p->tot*p->c;
            if(p->c<0) p->lm=p->mm=p->rm=p->c;
            else p->lm=p->mm=p->rm=p->sum;
            p->ch[0]->c=p->ch[1]->c=p->c;
            p->ch[0]->tc=p->ch[1]->tc=1;
            p->tc=0;
        }
        if(p->tr){
            int x=p->lm;p->lm=p->rm;p->rm=x;
            nod *y=p->ch[0];p->ch[0]=p->ch[1];p->ch[1]=y;
            p->tr=0;p->ch[0]->tr^=1;p->ch[1]->tr^=1;
        }
    }
    void update(nod *p){
        clear(p->ch[0]);clear(p->ch[1]);
        p->tot=p->ch[0]->tot+p->ch[1]->tot+1;
        p->sum=p->ch[0]->sum+p->ch[1]->sum+p->v;
        p->lm=max(p->ch[0]->lm,p->ch[0]->sum+p->v+max(0,p->ch[1]->lm));
        p->mm=max(p->ch[0]->mm,max(p->ch[1]->mm,max(0,p->ch[0]->rm)+p->v+max(0,p->ch[1]->lm)));
        p->rm=max(p->ch[1]->rm,max(0,p->ch[0]->rm)+p->v+p->ch[1]->sum);
    }
    void rotate(nod *x,bool t){
        nod *y=x->pr,*z=y->pr,*b=x->ch[t^1];
        b->pr=y;y->pr=x;x->pr=z;y->ch[t]=b;x->ch[t^1]=y;
        if(z->ch[0]==y) z->ch[0]=x;
        else if(z->ch[1]==y) z->ch[1]=x;
        update(y);update(x);
    }
    void splay(nod *x,nod *obj){
        while(x->pr!=obj){
            nod *y=x->pr,*z=y->pr;
            if(z==obj&&y->ch[0]==x) rotate(x,0);
            else if(z==obj&&y->ch[1]==x) rotate(x,1);
            else if(z->ch[0]==y&&y->ch[0]==x){rotate(y,0);rotate(x,0);}
            else if(z->ch[1]==y&&y->ch[1]==x){rotate(y,1);rotate(x,1);}
            else if(z->ch[1]==y){rotate(x,0);rotate(x,1);}
            else{rotate(x,1);rotate(x,0);}
        }
        if(obj==NIL) root=x;
    }
    nod* get(int k){
        nod *p=root;
        clear(p);
        while(p->ch[0]->tot+1!=k){
            if(p->ch[0]->tot+1>k) p=p->ch[0];
            else{k-=p->ch[0]->tot+1;p=p->ch[1];}
            clear(p);
        }
        return p;
    }
    void newnod(nod *pre,nod **p,int t){
        *p=new nod;
        (*p)->v=(*p)->sum=(*p)->lm=(*p)->mm=(*p)->rm=t;(*p)->tot=1;(*p)->tc=(*p)->tr=0;
        (*p)->ch[0]=(*p)->ch[1]=NIL;(*p)->pr=pre;
    }
    void insert(int pos,int t){
        if(!pos){
            if(root==NIL) newnod(NIL,&root,t);
            else{
                splay(get(1),NIL);
                newnod(root,&root->ch[0],t);
                splay(root->ch[0],NIL);
            }
        }
        else if(pos==root->tot){
            splay(get(root->tot),NIL);
            newnod(root,&root->ch[1],t);
            splay(root->ch[1],NIL);
        }
        else{
            splay(get(pos),NIL);
            splay(get(pos+1),root);
            newnod(root->ch[1],&root->ch[1]->ch[0],t);
            splay(root->ch[1]->ch[0],NIL);
        }
    }
    void del(nod *p){
        queue<nod*> Q;
        Q.push(p);
        while(!Q.empty()){
            nod *q=Q.front();Q.pop();
            if(q->ch[0]!=NIL) Q.push(q->ch[0]);
            if(q->ch[1]!=NIL) Q.push(q->ch[1]);
            delete q;
        }
    }
    void erase(int L,int R){
        if(L==1&&R==root->tot) del(root);
        else if(L==1){
            splay(get(R+1),NIL);
            del(root->ch[0]);
            root->ch[0]=NIL;
            update(root);
        }
        else if(R==root->tot){
            splay(get(L-1),NIL);
            del(root->ch[1]);
            root->ch[1]=NIL;
            update(root);
        }
        else{
            splay(get(L-1),NIL);
            splay(get(R+1),root);
            del(root->ch[1]->ch[0]);
            root->ch[1]->ch[0]=NIL;
            update(root->ch[1]);update(root);
        }
    }
    void change(int L,int R,int t){
        if(L==1&&R==root->tot){root->tc=1;root->c=t;}
        else if(L==1){
            splay(get(R+1),NIL);
            root->ch[0]->tc=1;root->ch[0]->c=t;
            clear(root->ch[0]);update(root);
        }
        else if(R==root->tot){
            splay(get(L-1),NIL);
            root->ch[1]->tc=1;root->ch[1]->c=t;
            clear(root->ch[1]);update(root);
        }
        else{
            splay(get(L-1),NIL);
            splay(get(R+1),root);
            root->ch[1]->ch[0]->tc=1;root->ch[1]->ch[0]->c=t;
            clear(root->ch[1]->ch[0]);update(root->ch[1]);update(root);
        }
    }
    void reverse(int L,int R){
        if(L==1&&R==root->tot){root->tr^=1;}
        else if(L==1){
            splay(get(R+1),NIL);
            root->ch[0]->tr^=1;
            clear(root->ch[0]);update(root);
        }
        else if(R==root->tot){
            splay(get(L-1),NIL);
            root->ch[1]->tr^=1;
            clear(root->ch[1]);update(root);
        }
        else{
            splay(get(L-1),NIL);
            splay(get(R+1),root);
            root->ch[1]->ch[0]->tr^=1;
            clear(root->ch[1]->ch[0]);update(root->ch[1]);update(root);
        }
    }
    void getsum(int L,int R){
        if(L==1&&R==root->tot){
            clear(root);
            printf("%d\n",root->sum);
        }
        else if(L==1){
            splay(get(R+1),NIL);
            clear(root->ch[0]);
            printf("%d\n",root->ch[0]->sum);
        }
        else if(R==root->tot){
            splay(get(L-1),NIL);
            clear(root->ch[1]);
            printf("%d\n",root->ch[1]->sum);
        }
        else{
            splay(get(L-1),NIL);
            splay(get(R+1),root);
            clear(root->ch[1]->ch[0]);
            printf("%d\n",root->ch[1]->ch[0]->sum);
        }
    }
    void maxsum(){
        clear(root);
        printf("%d\n",root->mm);
    }
};

int main(){
    Splay T;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        int t;
        scanf("%d",&t);
        T.insert(i-1,t);
    }
    for(int i=1;i<=m;i++){
        int  pos,tot;
        char ord[11];
        scanf("%s%d%d",ord,&pos,&tot);
        if(ord[0]=='I'){
            for(int j=1;j<=tot;j++){
                int t;
                scanf("%d",&t);
                T.insert(pos+j-1,t);
            }
        }
        else if(ord[0]=='D') T.erase(pos,pos+tot-1);
        else if(ord[0]=='M'&&ord[2]=='K'){
            int t;
            scanf("%d",&t);
            T.change(pos,pos+tot-1,t);
        }
        else if(ord[0]=='R') T.reverse(pos,pos+tot-1);
        else if(ord[0]=='G') T.getsum(pos,pos+tot-1);
        else T.maxsum();
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值