【總結】 伸展樹Splay
阿新 • • 發佈:2018-11-06
挖坑待補
前言
感覺我在聯賽還差4天的時候學習Splay有點慌,但還是要學一下。
定義
我們先對Splay的陣列進行一些定義:
struct node{
int ff,siz,cnt,ch[2],val;
//ff表示父親,siz表示子樹大小,ch表示兒子,cnt表示與這個點權值相同的點的個數,val表示權值。
}t[N<<2];
操作
我們的Splay應該要支援以下幾個操作:
- 插入
- 刪除
- 查詢排名為k的數
- 查詢k的排名
- 查詢k的前驅
- 查詢k的後繼
- 分裂(不會)
- 合併(啟發式合併)
程式碼如下:
#include<bits/stdc++.h> using namespace std; const int N=500010; int root,tot; inline int gi(){ int sum=0,f=1;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return f*sum; } class SplayTree{ private: struct node{ int ff,siz,cnt,ch[2],val; //ff表示父親,siz表示子樹大小,ch表示兒子,cnt表示與這個點權值相同的點的個數,val表示權值。 }t[N<<2]; inline void pushup(int x){t[x].siz=t[x].cnt+t[t[x].ch[0]].siz+t[t[x].ch[1]].siz;} inline void rotate(int x){ int y=t[x].ff,z=t[y].ff; int k=(x==t[y].ch[1]); t[z].ch[y==t[z].ch[1]]=x; t[x].ff=z; t[y].ch[k]=t[x].ch[k^1]; t[t[x].ch[k^1]].ff=y; t[x].ch[k^1]=y; t[y].ff=x; pushup(y);pushup(x); } public: inline void Splay(int x,int goal){ while(t[x].ff!=goal){ int y=t[x].ff,z=t[y].ff; if(z!=goal) (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y); rotate(x); } if(!goal)root=x; } inline void find(int x){ int u=root; if(!u)return; while(t[u].val!=x && t[u].ch[x>t[u].val]) u=t[u].ch[x>t[u].val]; Splay(u,0); } inline void Insert(int x){ int u=root,ff=0; while(u && t[u].val!=x){ff=u;u=t[u].ch[x>t[u].val];} if(u)t[u].cnt++; else{ u=++tot; t[u].cnt=t[u].siz=1;t[u].val=x; t[u].ff=ff;t[u].ch[0]=t[u].ch[1]=0; if(ff)t[ff].ch[x>t[ff].val]=u; } Splay(u,0); } inline int Next(int x,int f){//f=1表示後繼,f=0表示前驅 find(x); int u=root; if(t[u].val>x && f)return u; if(t[u].val<x && !f)return u; u=t[u].ch[f]; while(t[u].ch[f^1])u=t[u].ch[f^1]; return u; } inline void Delete(int x){ int last=Next(x,0),nxt=Next(x,1); Splay(last,0);Splay(nxt,last); int del=t[nxt].ch[0]; if(t[del].cnt>1){t[del].cnt--;Splay(del,0);} else t[nxt].ch[0]=0; } inline int kth(int x){ int u=root; if(t[u].siz<x)return 0; while(1){ int y=t[u].ch[0]; if(t[y].siz<x && t[y].siz+t[u].cnt>=x)return t[u].val; if(t[y].siz>=x)u=y; else{ x-=t[y].siz+t[u].cnt; u=t[u].ch[1]; } } } inline int Val(int u){ return t[u].val; } inline int ch0size(){ return t[t[root].ch[0]].siz; } }Splay; int main(){ int n=gi(); Splay.Insert(2147483647); Splay.Insert(-2147483648); while(n--){ int opt=gi(),x=gi(); if(opt==1)Splay.Insert(x); if(opt==2)Splay.Delete(x); if(opt==3){ Splay.find(x); printf("%d\n",Splay.ch0size()); } if(opt==4)printf("%d\n",Splay.kth(x+1)); if(opt==5)printf("%d\n",Splay.Val(Splay.Next(x,0))); if(opt==6)printf("%d\n",Splay.Val(Splay.Next(x,1))); } return 0; }