資料結構入門6 文藝平衡樹(Splay)

2021-08-06 01:38:39 字數 1505 閱讀 5924

早就聽說 splay 就是不管幹什麼都splay一下就可以了,但是聽說傻可開腦洞打**打了250行,驚恐。

於是先學treap結果沒想到一除錯就搞了三個月。但是其實寫過treap再學splay就相對容易一些了。

那就先學只有區間翻轉的文藝平衡樹。

一開始一直弄不懂它的翻轉操作,感覺很迷。但是其實和treap很像,只不過是以翻兩下為一組,然後每次splay把節點旋到指定位置。在三點一線的時候,先旋轉x的父親,再旋轉x,除此之外都直接旋轉x就好了。

除此之外還要注意一些細節問題。

乙個是關於新增虛節點的問題。比如我們要翻轉[l,r]這個區間,我們可以把r+1這個點splay到跟,然後把l-1這個點splay到跟的左兒子,然後直接把l-1的右兒子打上標記。但是如果l==1或r==n,那樣就必須新增乙個能表示l-1(0)的節點和乙個能表示r+1(n+1)的節點。

splay有兩種寫法,白書上是沒有父親指標的,但是有父親指標的適用性更強。

模板題

//serene

#include#include#include#include#include#includeusing namespace std;

const int maxn=1e5+10;

int n,m,root;

int aa;char cc;

int read()

struct nodenode[maxn];

void bld(int pos,int l,int r)

if(pos!=l) node[pos].son[0]=(pos+l)>>1;

if(pos!=r) node[pos].son[1]=(pos+2+r)>>1;

node[node[pos].son[0]].fa=node[node[pos].son[1]].fa=pos;

bld(node[pos].son[0],l,pos-1); bld(node[pos].son[1],pos+1,r);

node[pos].sum+=node[node[pos].son[0]].sum+node[node[pos].son[1]].sum+1;

}void ud(int pos)

swap(node[pos].son[0],node[pos].son[1]);

if(node[pos].son[0]) node[node[pos].son[0]].laz^=1;

if(node[pos].son[1]) node[node[pos].son[1]].laz^=1;

node[pos].laz=0;

}int find(int pos,int x)

void rotate(int pos,int &to)

}void splay(int pos,int &to)

rotate(pos,to); }}

void fz(int l,int r)

void dfs(int pos)

dfs(root);

return 0;

}

BZOJ 3223 文藝平衡樹

您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 翻轉乙個區間,例如原有序序列是5 4 3 2 1,翻轉區間是 2,4 的話,結果是5 2 3 4 1 n,m 100000 splay拿來練翻轉 這題就只用支援翻轉,很裸 翻轉區間 x,y 的操作 提取該區間,打乙個bo...

bzoj3223 文藝平衡樹

bzoj3223 文藝平衡樹 description 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 翻轉乙個區間,例如原有序序列是5 4 3 2 1,翻轉區間是 2,4 的話,結果是5 2 3 4 1 input 第一行為n,m n表示初始序列有n個數,這個序列依次...

Splay bzoj3223文藝平衡樹

splay,中文名伸展樹,是由tarjan大神發明的 orz 本質上就是bst加上splay操作 把結點x旋轉到指定結點的下面。每次查詢完都把查到的數旋轉到根,就可以讓所有查詢的時間效率為均攤o logn 不知道為啥 大佬說是就是吧orz 因為splay可以通過伸展操作隨意改變樹的結構,只要把排名l...