poj3481 splaytree模板题

找不到错在哪里,先留着吧

/*
splay是以键值排序的!
三个操作:1 a b,z增加键值为b的点,值为a
         2,查询最大值
         3,查询最小值
需要的操作:rotate,splay,insert,findx,delete
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1000005
int pre[maxn],ch[maxn][2],size[maxn],key[maxn],num[maxn],root,tot;

void newnode(int &r,int fa,int k,int val){
    r=++tot;
    pre[r]=fa;
    ch[r][0]=ch[r][1]=0;
    key[r]=k;
    num[r]=val;
}
void pushup(int r){
    size[r]=0;
    if(ch[r][0]) size[r]+=size[ch[r][0]];
    if(ch[r][1]) size[r]+=size[ch[r][1]];
    size[r]+=1;
} 
void rotate(int x,int kind){//0左旋,1右旋
    int fa=pre[x];
    ch[fa][!kind]=ch[x][kind];
    pre[ch[x][kind]]=fa;
    if(pre[fa])
        ch[pre[fa]][ch[pre[fa]][1]==fa]=x;
    pre[x]=pre[fa];
    pre[fa]=x;
    ch[x][kind]=fa;
    pushup(fa);
    pushup(x);
}
void splay(int r,int goal){
    while(pre[r]!=goal){
        if(pre[pre[r]]==goal) rotate(r,ch[pre[r]][0]==r);
        else {
            int fa=pre[r];
            int kind=ch[pre[fa]][0]==fa;//fa的旋转方向,与fa所在子树相反
            if(ch[fa][kind]==r){rotate(r,!kind);rotate(r,kind);}
            else{rotate(fa,kind);rotate(r,kind);}
        }
    }
    if(goal==0) root=r;
    pushup(r);
}
void init(){
    root=tot=0;
    ch[root][0]=ch[root][1]=pre[root]=size[root]=num[root]=key[root]=0;
}
void insert(int k,int val){//插入键值为k的结点
    int r=root;
    if(r==0) {newnode(root,0,k,val);pushup(root);return;}
    while(ch[r][key[r]<k]) r=ch[r][key[r]<k];
    newnode(ch[r][key[r]<k],r,k,val);
    splay(ch[r][key[r]<k],0);//把k提上去作为根
    pushup(r);
}
int getth(int r,int pos){//返回第pos个结点的
    int t=size[ch[r][0]]+1;
    if(pos==t) return r;
    else if(pos<t) getth(ch[r][0],pos);
    else getth(ch[r][1],pos-t);
}
void remove(){//删除根节点
    if(ch[root][0]==0){root=ch[root][1];pre[root]=0;}//只有右子树
    else {
        int tmp=getth(ch[root][0],size[ch[root][0]]);
        splay(tmp,root);
        ch[tmp][1]=ch[root][1];
        pre[ch[root][1]]=tmp;
        root=tmp;
        pre[root]=0;
    }
    pushup(root);
}
int main(){
    int op,k,p;
    init();//建立一颗空树
    while(scanf("%d",&op)&&op){
        if(op==2){//最大值
            if(root==0) {
                puts("0");
                continue;
            }
            int ans=getth(root,size[root]);
            splay(ans,0);
            printf("%d
",num[ans]);
            remove();
            //debug();
        }
        else if(op==3){
            if(root==0){
                puts("0");
                continue;
            }
            int ans=getth(root,1);
            splay(ans,0);
            printf("%d
",num[ans]);
            remove();
            //debug();
        }
        else {
            scanf("%d%d",&k,&p);
            insert(p,k);//p是关键字,k是值
            //debug();
        }
    }
    return 0;
}

 终于过了:和上面做法有些不同,找到最大或最小的点,将其作为根,同时将前驱后缀提取出来当做子树

/*

*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define maxn 100005
#define inf 0x3f3f3f3f
int pre[maxn],ch[maxn][2],nums[maxn],keys[maxn],size[maxn],tot,root;

inline void newnode(int &r,int fa,int k,int val){
    r=++tot;
    ch[r][0]=ch[r][1]=0;
    pre[r]=fa;
    size[r]=1;
    nums[r]=val;
    keys[r]=k;
}
void init(){
    tot=root=0;
    pre[root]=ch[root][0]=ch[root][1]=size[root]=0;
}
inline void pushup(int x){
    size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}    
inline void rotate(int x,int kind){
    int fa=pre[x];
    ch[fa][!kind]=ch[x][kind];
    pre[ch[x][kind]]=fa;
    pre[x]=pre[fa];
    if(pre[fa])
        ch[pre[fa]][ch[pre[fa]][1]==fa]=x;
    ch[x][kind]=fa;
    pre[fa]=x;
    pushup(fa);
    pushup(x);
}
inline void splay(int x,int goal){
    while(pre[x]!=goal){
        if(pre[pre[x]]==goal) rotate(x,ch[pre[x]][0]==x);
        else {
            int fa=pre[x];
            int kind=ch[pre[fa]][0]==fa;
            if(ch[fa][kind]==x){
                rotate(x,!kind);
                rotate(x,kind);
            }
            else {
                rotate(fa,kind);
                rotate(x,kind);
            }
        }
    }
    pushup(x);
    if(goal==0) root=x;
}
int find(int key){
    if(root==0) return 0;
    int x=root;
    while(x && keys[x]!=key)
        x=ch[x][key>keys[x]];
    if(x) splay(x,0);
    return x;
}
int prev(){
    int x=ch[root][0];
    if(x==0) return 0;//ÎÞÇ°Çý
    while(ch[x][1])
        x=ch[x][1];
    return x; 
}
int succ(){
    int x=ch[root][1];
    if(x==0) return 0;//ÎÞºó¼Ì
    while(ch[x][0])
        x=ch[x][0];
    return x; 
}
void insert(int key,int num){
    if(root==0) {newnode(root,0,key,num);return;}
    int x=root,lastx=0;
    while(x){
        lastx=x;
        x=ch[x][key>keys[x]];
    }
    newnode(x,lastx,key,num);
    ch[lastx][key>keys[lastx]]=x;
    pre[x]=lastx;
    splay(x,0);
}

void del(int key){
    int x=find(key);
    if(x==0) return;    
    int tmp1=prev(),tmp2=succ();
    if(!tmp1 && !tmp2){root=0;return;}
    if(!tmp1){//Ö»ÓÐÓÒ×ÓÊ÷ 
        splay(tmp2,0);
        ch[tmp2][0]=0;
        pushup(tmp2);
        return;
    }
    if(!tmp2){//Ö»ÓÐ×ó×ÓÊ÷ 
        splay(tmp1,0);
        ch[tmp1][1]=0;
        pushup(tmp1);
        return;
    }
    splay(tmp1,0);
    splay(tmp2,tmp1);
    ch[tmp2][0]=0; 
    pushup(tmp2);pushup(tmp1);
}
int getth(int x,int pos){
    if(root==0) return 0;
    int t=size[ch[x][0]]+1;
    if(pos==t) return x;
    else if(pos<t) return getth(ch[x][0],pos);
    else return getth(ch[x][1],pos-t);
}
int main(){        
    int p,key,num,x;
    while(scanf("%d",&p)&&p){
        switch(p){    
            case 1:
                scanf("%d%d",&num,&key);
                insert(key,num);
                break;
            case 2:    
                x=getth(root,size[root]);
                if(x){
                    printf("%d
",nums[x]);
                    del(keys[x]);
                }    
                else printf("0
");
                break;
            case 3:
                x=getth(root,1);
                if(x){
                    printf("%d
",nums[x]);
                    del(keys[x]);
                }
                else printf("0
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zsben991126/p/9992390.html