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\n",num[ans]); remove(); //debug(); } else if(op==3){ if(root==0){ puts("0"); continue; } int ans=getth(root,1); splay(ans,0); printf("%d\n",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\n",nums[x]); del(keys[x]); } else printf("0\n"); break; case 3: x=getth(root,1); if(x){ printf("%d\n",nums[x]); del(keys[x]); } else printf("0\n"); } } return 0; }