splay POJ 3580SuperMemo

从搞acm以来,一直负责队内的图论,搜索,树形DP。今年的regional结束了,想学学数据结构了

splay用的是孟神的模板,发现splay就是一个splay操作,没什么困难的,果断搞起

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define mid (L+R>>1)
const int M = (int)1e6+10;
const int inf=~0u>>2;
int s[M],n,m;
struct splaytree{
    int cnt,root;
    int sz[M],ch[M][2],pre[M];
    int add[M],rev[M],minn[M],val[M];
    
    inline bool dir(int x){
        return ch[pre[x]][1]==x;
    }
    inline void link(int x,int y,int d){
        if(y)ch[y][d]=x;
        if(x)pre[x]=y;
    }
    inline void rotate(int x){
        int y=pre[x],d=dir(x);
        pushdown(y);pushdown(x);
        link(x,pre[y],dir(y));
        link(ch[x][!d],y,d);
        link(y,x,!d);
        pushup(y);
    }
    inline void splay(int x,int goal){
        pushdown(x);
        while(pre[x]!=goal){
            if(pre[pre[x]]==goal){
                rotate(x);
            } else{
                if(dir(x)==dir(pre[x])){
                    rotate(pre[x]);
                } else{
                    rotate(x);
                }
                rotate(x);
            }
        }
        pushup(x);
        if(goal==0)root=x;
    }
    void newnode(int &t,int v){
        t=++cnt;
        ch[t][0]=ch[t][1]=0;
        sz[t]=1;
        add[t]=rev[t]=0;
        val[t]=minn[t]=v;
    }
    void pushup(int t){
        sz[t]=sz[ch[t][0]]+sz[ch[t][1]]+1;
        minn[t]=min(val[t],min(minn[ch[t][0]],minn[ch[t][1]]));
    }
    void pushdown(int t){
        if(ch[t][0]){
            add[ch[t][0]]+=add[t];
            val[ch[t][0]]+=add[t];
            minn[ch[t][0]]+=add[t];
            rev[ch[t][0]]^=rev[t];
        }
        if(ch[t][1]){
            add[ch[t][1]]+=add[t];
            val[ch[t][1]]+=add[t];
            minn[ch[t][1]]+=add[t];
            rev[ch[t][1]]^=rev[t];
        }
        if(rev[t])swap(ch[t][0],ch[t][1]);
        rev[t]=add[t]=0;
    }
    void build(int L,int R,int &t,int p){
        if(R<L)return ;
        newnode(t,s[mid]);
        build(L,mid-1,ch[t][0],t);
        build(mid+1,R,ch[t][1],t);
        pre[t]=p;pushup(t);
    } 
    void init(int n){
        cnt=root=0;
        sz[0]=pre[0]=0;
        ch[0][0]=ch[0][1]=0;
        add[0]=rev[0]=0;
        minn[0]=val[0]=inf;
        newnode(root,inf);
        newnode(ch[root][1],inf);
        pre[cnt]=root,sz[root]=2;
        build(1,n,ch[ch[root][1]][0],ch[root][1]);
        pushup(ch[root][1]);pushup(root);
    }
    int select(int t,int k){
        pushdown(t);
        if(sz[ch[t][0]]==k)return t;
        if(sz[ch[t][0]]>k){
            return select(ch[t][0],k);
        }else{
            return select(ch[t][1],k-sz[ch[t][0]]-1);
        }
    }
    void get(int l,int r){
        splay(select(root,l-1),0);
        splay(select(root,r+1),root);
    }
    void Add(int l,int r,int d){
        get(l,r);
        int x=ch[ch[root][1]][0];
        add[x]+=d;
        minn[x]+=d;
        val[x]+=d;
        pushup(ch[root][1]);
        pushup(root);
    } 
    void reverse(int l,int r){
        get(l,r);
        int x=ch[ch[root][1]][0];
        rev[x]^=1;
    }
    int Min(int l,int r){
        get(l,r);
        int x=ch[ch[root][1]][0];
        return minn[x];
    }
    void del(int x){
        get(x,x);
        ch[ch[root][1]][0]=0;
        pushup(ch[root][1]);
        pushup(root);
    }
    void insert(int x,int y){
        get(x+1,x);
        newnode(ch[ch[root][1]][0],y);
        pre[ch[ch[root][1]][0]]=ch[root][1];
        pushup(ch[root][1]);
        pushup(root);
    }
    void revolve(int L,int R,int t){
        int len=(R-L+1);
        t=(t%len+len)%len;
        if(t==0)return;
        reverse(L,R-t);
        reverse(R-t+1,R);
        reverse(L,R); 
    }
}tree;


int main(){
    while(cin>>n){
        for(int i=1;i<=n;i++){
            scanf("%d",&s[i]);
        }
        tree.init(n);
        cin>>m;
        while(m--){
            char op[15];
            scanf("%s",op);
            if(op[0]=='A'){
                int x,y,d;
                scanf("%d%d%d",&x,&y,&d);
                tree.Add(x,y,d);
            } else if(op[0]=='R'&&op[3]=='E'){
                int x,y;
                scanf("%d%d",&x,&y);
                tree.reverse(x,y);
            } else if(op[0]=='R'&&op[3]=='O'){
                int x,y,t;
                scanf("%d%d%d",&x,&y,&t);
                tree.revolve(x,y,t);
            } else if(op[0]=='I'){
                int x,y;
                scanf("%d%d",&x,&y);
                tree.insert(x,y);
            } else if(op[0]=='D'){
                int x;
                scanf("%d",&x);
                tree.del(x);
            } else if(op[0]=='M'){
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%d\n",tree.Min(x,y));
            }
        }
    }
    return 0;
}




这个代码有186行之长。。。,可是发现核心的就是下面这点

inline bool dir(int x){
        return ch[pre[x]][1]==x;
    }
    inline void link(int x,int y,int d){
        if(y)ch[y][d]=x;
        if(x)pre[x]=y;
    }
    inline void rotate(int x){
        int y=pre[x],d=dir(x);
        pushdown(y);pushdown(x);
        link(x,pre[y],dir(y));
        link(ch[x][!d],y,d);
        link(y,x,!d);
        pushup(y);
    }
    inline void splay(int x,int goal){
        pushdown(x);
        while(pre[x]!=goal){
            if(pre[pre[x]]==goal){
                rotate(x);
            } else{
                if(dir(x)==dir(pre[x])){
                    rotate(pre[x]);
                } else{
                    rotate(x);
                }
                rotate(x);
            }
        }
        pushup(x);
        if(goal==0)root=x;
    }



就是个splay操作,完成一系列的翻转等等。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值