經過一天re
的洗禮,終於把指標版\(\mathrm\)趕出來了,淚目
看了一圈,居然沒有找到\(\mathrm\)的指標版題解,氣抖冷,指標黨什麼時候才能站起來!
先放上自己的部落格
雖然都是平衡樹,但是\(\mathrm\)和\(\mathrm\)是不一樣的
\(\mathrm\)維持平衡的條件是每個節點隨機賦予的優先順序,但\(\mathrm\)沒有這個條件
\(\mathrm\)維持平衡的條件就是:把乙個節點插入到最底之後,直接用splay
操作旋轉到根
雖然單次操作可能較慢,但是這樣保證了整棵\(\mathrm\)的期望樹高為\(o(\log n)\),總體複雜度是確定的,相較於\(\mathrm\)來說更穩定
(此處僅以某平衡樹模板為例)
(提前說明,因為這是指標版,所以重心在於說明指標版可能出現的問題,關於splay
或者rotate
這些人盡皆知的函式的細節還煩請大家左轉其它大佬的優質題解作進一步學習)
首先要說明,\(\mathrm\)的很多函式是不需要遞迴的(區別於\(\mathrm\))
(以下以\(x\)代表上述題目中輸入要求的操作的第二引數)
struct node
bool get_dir() //判斷某節點是其父親的左兒子還是右兒子(冒號後面的0對應沒有父親的情況,可以隨便賦值)
void update()
}tree[maxn],*now=tree,*root=null;
insert
void insert(int x)
splay(r,null);return;
}
delete
(為免與c++
中的關鍵字衝突,建議將函式名仿照stl
的習慣改為erase
)
拋開各種情況的話,delete
本身操作不難,要不就是某節點->cnt-=1
(cnt>1
),要不就是某個節點=null
(cnt==1
),都是正常操作
(注意!因為將某個節點=null
時,這個節點對應的父子關係(例如在理想情況中,被刪除的節點對應的是r->son[1]
)也要被修改為null
,所以在這種情況下,被刪除的節點要加乙個引用&
,具體見下)
(如果cnt>1
的話,最後不要忘了splay
)
void erase(int x)
get_lower(upper) & find
get_rank
splay & rotate
get_kth
這個函式本身是最簡單的,分三類討論,注意向右兒子跳時要減去左兒子的size
和節點本身的cnt
,還有到最後不要忘了splay
即可
int get_kth(int x)
}}
乙個小函式
#include#include#include#includeconst int maxn=1e5+2;
struct splay
bool get_dir() //判斷某節點是其父親的左兒子還是右兒子(後面的0是隨便給的)
void update()
}tree[maxn],*now=tree,*root=null;
int get_size(node *r)
void link(node *fa,node *son,int d) //d決定son是fa的左兒子還是右兒子
void rotate(node *r)
void splay(node *r,node *goal) //r要一直splay到goal的兒子(goal為null時,r就splay到根節點)
if( !goal ) root=r;return; //goal為null,則r已經被splay到根節點,修改root為r }
void find(int x) //查x並且splay到根節點
// void merge(node *l,node *r)
// //
// void split(int len,node *&left,node *&right)
// int get_rank(int x)
int get_kth(int x)
} }
void insert(int x)
splay(r,null);return; }
node *get_lower(int x)
node *get_upper(int x)
void erase(int x)
// void run(node *r)
// }bt;
int main() }
return 0;
}//1. get_lower和get_upper的r可能為空
//2. get_rank時,因為是將u的左兒子rotate到根節點,所以應該是u->size - u->son[1]->size
//3. erase時,要看r->son[0]和l->son[1]哪個存在 (注意加引用,因為可能要將del改為null)
幾個困擾了我很久坑點在上面**最後的注釋裡寫了
ed:祝學習資料結構的各位能有乙個肝疼的早上美妙的1a記錄!
\(by\ the\ way\),推薦大家以後用極限資料時,試試用climits
這個庫(我上面已經用了)
#include#include//...
#define int_min (-2147483647 - 1)
#define int_max 2147483647
#define uint_max 0xffffffffu
#define long_min (-2147483647l - 1)
#define long_max 2147483647l
#define ulong_max 0xfffffffful
#define llong_max 9223372036854775807ll
#define llong_min (-9223372036854775807ll - 1)
#define ullong_max 0xffffffffffffffffull
//...
數列 專殺Splay版
時間限制 3 sec 記憶體限制 128 mb 提交 49 解決 7 輸入乙個數列,你需要進行如下操作 1 把編號為i的數值改為k 2 輸出從小到大排序後第k個數 輸入檔案第一行包含兩個整數n m,分別表示數列長度與操作個數。第二行有n個整數,為初始數列中的n個整數。接下來m行每行如果只有乙個整數k...
this指標詳解
兩個被過載的賦值操作符引用了乙個特殊的關鍵字this 當我們寫如下 時 string name1 orville name2 wilbur name1 orville wright 在賦值操作符中this 指向name1 更一般的情況下在類成員函式中this 指標被自動設定為指向左側的類物件我們通過...
this指標詳解
什麼是this指標 this是指向例項化物件本身時候的乙個指標,裡面儲存的是物件本身的位址,通過該位址可以訪問內部的成員函式和成員變數。乙個物件的this指標並不是物件本身的一部分,其不會影響sizeof 物件 的結果。this指標的用處 this作用域是在類內部,當在類的非靜態成員函式中訪問類的非...