zoukankan      html  css  js  c++  java
  • bzoj1208splay模板题

    想试下新找的板子,没想到交上去CE了。。懒得调。。以后有机会就改

    /*
    用type标记当前树上的是宠物还是人
    每次求前驱后缀,删掉最近的那个点
    */
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    #define maxn 1000100
    #define L ch[r][0]
    #define R ch[r][1]
    #define KT ch[ch[r][1]][0]
    
    struct Splay{
        int pre[maxn],sz[maxn],ch[maxn][2],val[maxn],rt,tot;
        int flag;
        inline void newnode(int &r,int fa,int key){
            r=++tot;
            L=R=0;
            pre[r]=fa;
            val[r]=key;
            sz[r]=1;
            sz[L]=sz[R]=0;
        }   
        inline void pushup(int r){
            sz[r]=1;
            if(L) sz[r]+=sz[L];
            if(R) sz[r]+=sz[R];
        }
        inline void init(){//加两个边界
            rt=tot=flag=0;
            ch[rt][0]=ch[rt][1]=sz[rt]=pre[rt]=0;
            newnode(rt,0,-99999999);
            newnode(ch[rt][1],rt,9999999);
            memset(sz,0,sizeof sz);
        }
        inline void rotate(int x,int f) {
            int y=pre[x];
            ch[y][!f] = ch[x][f];
            pre[ ch[x][f] ] = y;
            pre[x] = pre[y];
            if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x;
            ch[x][f] = y;
            pre[y] = x;
            pushup(y);
        }
        inline void splay(int x,int goal) { //将x旋转到goal的下面
            while(pre[x] != goal) {
                if(pre[pre[x]] == goal) rotate(x , ch[pre[x]][0] == x);
                else   {
                    int y=pre[x],z=pre[y];
                    int f = (ch[z][0]==y);
                    if(ch[y][f] == x) rotate(x,!f),rotate(x,f);
                    else rotate(y,f),rotate(x,f);
                }
            }
            pushup(x);
            if(goal==0) rt=x;
        }
    
        inline void insert(int &r,int key,int fa){
            if(!r){newnode(r,fa,key);splay(r,0);return;}
            else if(key<val[r]) insert(L,key,r);
            else insert(R,key,r);
            pushup(r);
        }
        inline int findkth(int r,int k){//找第k大的那个结点的值
            if(k==sz[L]+1) {splay(r,0);return val[r];}
            else if(k<sz[L]+1)
                return findkth(L,k);
            else return findkth(R,k-sz[L]-1);
        }
        inline int find(int r,int key){//找键值为key的结点
            if(!r) return 0;//不存在这个键值
            else if(key==val[r]) return r;
            else if(key<val[r]) find(L,key);
            else find(R,key);
        }
        void remove(){
            int t=rt;
            if(ch[rt][1]){//删掉根节点并以后缀作为根
                rt=ch[rt][1];
                splay(getmin(rt),0);
                ch[rt][0]=ch[t][0];
                if(ch[rt][0]) pre[ch[rt][0]]=rt;
            }
            else rt=ch[rt][0];
            pre[rt]=0;
            pushup(rt);
        }
        void findpre(int r,int key,int &ans){//找前驱结点(找值比key小的的最大的结点)
            if(!r) return;
            if(key>=val[r]) {ans=r;findpre(R,key,ans);}
            else findpre(L,key,ans);
        }
        void findsucc(int r,int key,int &ans){///找后继
            if(!r) return;
            if(key<=val[r]) {ans=r;findsucc(L,key,ans);}
            else findsucc(R,key,ans);
        }
        inline int getmin(int r){while(L) r=L;return r;}
        inline int getmax(int r){while(R) r=R;return r;}
        
        inline void vist(int r){
            if(r){
                printf("结点%2d : 左儿子  %2d   右儿子  %2d   val:%2d sz=%d
    ",r,L,R,val[r],sz[r]);
                vist(L);
                vist(R);
            }
        }
        void debug() {
            puts("");
            vist(rt);
            puts("");
        }
    }spt;
    int main(){
        int n,a,b,ans;
        while(scanf("%d",&n)==1){
            spt.init();
            ans=0;
            for(int i=1;i<=n;i++){
                scanf("%d%d",&a,&b);
               // spt.debug();
                if(spt.sz[spt.rt]==2){
                    spt.flag=a;
                    spt.insert(spt.rt,b,0);
                }
                else {
                    if(spt.flag==a) spt.insert(spt.rt,b,0);
                    else {
                        int tmp1,tmp2;
                        spt.findpre(spt.rt,b,tmp1);
                        spt.findsucc(spt.rt,b,tmp2);
                        if(abs(b-spt.val[tmp1])<=abs(b-spt.val[tmp2])){
                            ans+=abs(b-spt.val[tmp1]);
                            spt.splay(tmp1,0);
                            spt.remove();
                        }
                        else {
                            ans+=abs(b-spt.val[tmp2]);
                            spt.splay(tmp2,0);
                            spt.remove();
                        }
                    }
                }
               // spt.debug();
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    【Python】练习题
    Markdown 常见用法
    程序员个性注释图案
    Class.getResource和ClassLoader.getResource的区别分析
    spring源码分析(二)
    spring源码分析(一)
    加密、解密、公钥,私钥、Https协议
    二叉查找树、红黑树
    HashMap、ConcurrentHashMap
    springIOC
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10003581.html
Copyright © 2011-2022 走看看