子樹大小平衡樹

2022-07-22 05:24:17 字數 2792 閱讀 2715

#include#define mxn 100000+3

#define max(a,b) (a>b?a:b)

#define min(a,b) (a#define nil 0

#define left false

#define right true

int val[mxn],size[mxn],fa[mxn],left[mxn],right[mxn],recycle[1001

],root;

int ntop,rtop=-1

;int

newnode()

int newnode(int

k)void rotate(int

now)

if(left[f]==now)

if(right[f]==now)

fa[f]=now;

size[f]=size[left[f]]+size[right[f]]+1

; size[now]=size[left[now]]+size[right[now]]+1

;

if(fa[now]==nil) root=now;

return;}

intmtl,mtr,mtb,mtrt;

void maintain(int now,bool

type)

else

if(size[right[mtl]]>size[mtr])

else

return

; }

if(type==right)

else

if(size[left[mtr]]>size[mtl])

else

return

; }

maintain(left[mtrt],left);

maintain(right[mtrt],right);

maintain(mtrt,left);

maintain(mtrt,right);

return;}

int search(int now,int

k)int insert(int &now,int

ins)

else

insert(left[now],ins);

}else

else

insert(right[now],ins);

}maintain(now,val[ins]>val[now]);

}return

ins;

}void remove(int now,int

k)

else

if(left[now]==nil)

else

if(right[now]==nil)

else

}else

return;}

intselect(int now,int

k)int rank(int now,int

k)int get_prev(int now,int

k)int get_succ(int now,int

k)int

main()

return0;

}

size balanced tree

子樹大小平衡樹是一種平衡樹,利用子樹大小維護平衡。滿足下面性質的二叉搜尋樹稱為sbt:

除根外,每棵樹的大小不小於其兄弟的兒子的大小。

性質十分簡單。由於具有對稱性(即若lr互為兄弟,則l大小不小於r的兒子大小,同時r大小不小於l的兒子大小),因此可以使樹保持平衡。

sbt基本操作為旋轉。旋轉與splay定義不同(貌似與很多平衡樹相同),左旋一棵樹指使其右子樹的根成為這棵樹新的根,右旋與左旋對稱。

主要的維護利用maintain,分以下四種情況:

1、若某點右子樹大小小於其左兒子的左子樹大小,則右旋其本身,對稱的情況是某點左子樹大小小於其右兒子的右子樹大小,則左旋其本身;

2、若某點右子樹大小小於其左兒子的右子樹大小,則先左旋其左子樹,再右旋其本身,另一種情況與這種情況對稱。

旋轉之後,有一些樹的大小發生變化,那麼需要繼續maintain,直到滿足sbt性質。若上述maintain了子樹a,則先maintaina的左右子樹,再maintaina本身。

有一種對maintain的改良方法,即maintain時只關注某乙個子樹是否小於其兄弟的兒子。不過我並不感覺改良了多少,大概改良了maintain次數,不過只是把四種情況分開討論,原本四種情況也不會重疊。

跑得還是比較快的。

ps:子樹大小平衡樹雖然**簡單,但是有特殊情況不得不考慮:由於判斷平衡時找到了自己的孫子,但這對於那些連兒子都沒有的葉子結點來說是無能為力的,如果maintain葉子結點,用指標寫會由於取null的值導致re,用上述**,即規定乙個有值的null來寫,則會因為null有兒子導致判斷錯誤從而進行不必要的旋轉甚至最終爆棧。因此maintain時可以不對葉子結點進行處理,也可以maintain時判斷一下null的情況。上述**每次maintain都將null的兒子指向自己,防止錯誤判斷。

樹的子樹大小與深度

51nod 2281 這題用的是並查集的思想,由於給定了父子關係,所以很容易知道建立並查集,最後find每個數,並且find函式找到一次某個節點,就給這個節點計數一次,代表這個節點有這個子節點 include using namespace std int num 1005 pre 1005 voi...

容器大小 平行板電容器動態平衡

關於平行板電容器的動態平衡問題,我們先來簡單回顧下知識點,之後會詳細講講其中乙個難點 關於某點的電勢能與電勢的變化。平行板電容器動態平衡的兩類模型 若電容器與電源相連,則整個動態平衡過程中電容器的電勢差u不變 若電容器與電源斷開,則整個動態平衡過程中電容器的電荷量q不變 所涉及到的幾個公式 通常來說...

樹的應用 求有根樹所有子樹大小

給出一棵節點編號為1 n的有根樹,計算它的所有子樹的大小 輸入格式 第一行為乙個整數n 第二行是n個整數,依次表示編號為1到n的節點的父親編號。特別的,父親編號為0表示這個點是根。輸出格式 輸出一行,n個整數,依次表示編號為1到n的節點為根的子樹的大小。題目的特殊性在於樹的構建 第一,這不是二叉樹,...