splay是基本操作,rotate是splay的基本操作。splay(now,root)把now splay到root的下面。單旋和雙旋就不說了。我們可以簡化操作,如果是一字型(方向相同)則先旋father,否則先旋now。然後再旋now。
rotate now是指將now繞father rotate。有兩個方向,表示now是father的左兒子還是右兒子。
bool flag(int
now)
通過方向標記,我們可以將兩個方向的rotate合成乙個。void rotate(int now)
具體步驟請自行腦補。
別忘了rotate完成後要updata。
void updata(int
pos)
int kth(int
now,int th)
int pre(int
val)
int succ(int
val)
首先要找到乙個合適的位置int getpos(int
now,int val)
但是我們並不能保證這個點是大於還是小於插入節點void insert(int root,int
pos,int val)
int tmp=son[root][0];key[pos]=val;
son[root][0]=pos;father[pos]=root;
son[pos][0]=tmp;father[tmp]=pos;
updata(pos);updata(root);
splay(pos,0);
}
我們把剛好比插入點大的點作為根,在左子樹插入。如果根小於插入點,則要將根的後繼變成根(!!!注意不是根的右兒子!!!)
至此splay的基本操作我們都完成了。
對於有重複元素的題,我們必須小心小心再小心。find的時候必須找最小序號的哪乙個,pre和succ查詢的數可能不在splay中,要做一點處理。
void
dele(int
root,int
val)
int rank(int
now,int val)
int find(int now,int val)
#include
#include#include#include#include#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
intconst maxn=1000000,inf=2147483647;
int n,size[maxn+10],key[maxn+10],father[maxn+10],son[maxn+10][10];
void updata(int pos)
bool flag(int
now)
void rotate(int
now)
void splay(int
now,int root)
rotate(now);
}}int getpos(int
now,int val)
int kth(int
now,int th)
int pre(int val)
int succ(int val)
void insert(int root,int pos,int val)
int tmp=son[root][0];key[pos]=val;
son[root][0]=pos;father[pos]=root;
son[pos][0]=tmp;father[tmp]=pos;
updata(pos);updata(root);
splay(pos,0);
}int main()
printf("%d\n",ans);
return 0;
}
#include
#include
#include
#include
#include
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using
namespace
std;
intconst maxn=100000,inf=2147483647;
int n,key[maxn+10],mx[maxn+10],mi[maxn+10],size[maxn+10],father[maxn+10],son[maxn+10][10];
bool flag(int now)
void updata(int now)
void rotate(int now)
void splay(int now,int root)
}int find(int now,int val)
int kth(int now,int val)
int succ(int now)
void insert(int root,int pos,int val)
key[pos]=val;int tmp=son[root][0];
son[root][0]=pos;father[pos]=root;
son[pos][0]=tmp;father[tmp]=pos;
updata(pos);updata(root);
}int pre(int now)
void dele(int root,int val)
int rank(int now,int val)
int main()
else
if(opt==4)
else
if(opt==5)
else
}return
0;}
總結 伸展樹Splay
感覺我在聯賽還差4天的時候學習splay有點慌,但還是要學一下。我們先對splay的陣列進行一些定義 struct nodet n 2 我們的splay應該要支援以下幾個操作 如下 includeusing namespace std const int n 500010 int root,tot ...
學習筆記第六節 伸展樹splay
正文 說到伸展樹,大家想到的可能是複雜,冗長,很容易打錯,思路卻很好理解。沒錯,伸展樹的確是這麼乙個東西,如果你做多了題,學會用它之後,你就會覺得很得心應手,輕鬆面對許多高階資料結構題。這個當然也是乙個鍛鍊人的耐心的東西,有乙份 調了4天emm。伸展樹是一棵二叉搜尋樹,就是說,它是一棵單一關鍵字排序...
資料結構 Splay伸展樹 普通平衡樹
題目描述 您需要寫一種資料結構 可參考題目標題 來維護一些數,其中需要提供以下操作 插入x數 刪除x數 若有多個相同的數,因只刪除乙個 查詢x數的排名 若有多個相同的數,因輸出最小的排名 查詢排名為x的數 求x的前驅 前驅定義為小於x,且最大的數 求x的後繼 後繼定義為大於x,且最小的數 輸入 第一...