首先表示對yyb大佬的崇高敬意雖然大佬根本不知道林蔭是個神馬東西
!在這裡學的:yyb大佬的教程!
好吧,我回來填坑了!
首先宣告一下定義
structp;t陣列就是記錄整顆樹的陣列,v代表當前點的權值,ff代表當前點的父親,ch[0,1]分別代表左右子樹(左子樹上的元素小於根,右子樹則大於),size代表以該節點為根的子樹中元素個數,cnt代表當前點上有多少個元素(權值均為v)pushup維護sizep t[
150001];
void pushup(int下面是一次旋轉rotate先想一下一次旋轉會造成什麼影響:假設當前節點為x,父親為y,將x旋轉到y上,x是y的k子樹(k=0或1,代表左右子樹)那麼:x)
x的k^1兒子會變成y(因為(y>x)==k^1,那麼假如k=0,y>x,那麼將y作為x的右子樹保證大於x,若k=1,y
原來x的k^1兒子被過繼給y做k兒子(假定該兒子為s,若k=0,s>x且s
沒了
然後注意適當的時候維護他們的ff就可以了。
void rotate(int下面就是splay的核心了,splay,這也是它快的原因splay的作用是將x旋轉成為goal的兒子,若goal==0則將x旋轉到root的位置。現在先想一種情況:x)
好的,有點大,引用自yyb大佬的部落格。
考慮這種情況,現在我們將x旋轉到root(z)的位置,然後我們查詢b的位置,旋轉前查詢路徑:z—》y—》x—》b
但是旋轉後呢?(自己畫個圖)路徑還是由x—》z—》y—》b,因為這個時候,b作為x的右兒子被過繼給了y,而b的養父y由於被x旋轉下來的z壓著,留在了社會的最底層(批鬥x)這時,樹的深度沒有變化。
然而無論如何向上層社會進步的同時都會付出一定的代價,x向上旋轉的時候b一定會被過繼給y,兩次連續的旋轉後就留在了社會底層,這就不平衡了對吧。那我們就順便提高一波y的社會地位,先將y向上旋轉,這個時候y的左子樹是x,右子樹是z,然後再將x旋轉上去。
可能有的小可愛已經發現了乙個問題,上面所說的問題出現在y和x與自己的父親大小關係相同的情況下,換言之就是x和y同為自己父親的左或者右子樹。
因為如果y和x不同為自己父親的左或右子樹的話,y不會受到x和z旋轉的影響,也就是說y和z在x的不同子樹上,不會出現y被z壓著的情況,這個時候,樹的深度就變淺了hhhhh。
好了,林蔭開始槓精了,如果在把x翻上去之後要查詢z的兒子的話怎麼辦?那就再把z的兒子翻上來不就好啦,翻著翻著樹就變矮變寬了,這也就是平衡樹的精髓所在。
對了,這個時候,如果目標goal==0的話,root就是x啦
void splay(int x,intinsert就沒啥好說的了,一溜煙往下找,找到了計數器++,找不到自力更生新開個點goal)
rotate(x);
}if(goal==0
)
}
void insert(intfind的操作意義是找到權值為x的節點並將其翻到樹頂,也沒啥可說的,一溜煙往下找,找到了就翻上去即可。x)
if(t[u].v==x)
else
splay(u,0);
}
void find(int下面是前驅字尾查詢操作,f=0代表查詢前驅,=1代表查詢字尾。x) splay(u,0);
}
int next(int x,int這裡有一點需要注意,因為find(x)中有splay(u,0)語句了,實際上這個時候u點的權值就是x,這裡是yyb大佬部落格中的乙個小坑,中間兩個if是沒有意義的。f)
if(t[u].vf)
u=t[u].ch[f];
while(t[u].ch[f^1
])
return
u;}
下面是kth(實際上是將序列從小到大排開第k個)這個挺簡單的。
int kth(int最後是delete怎樣刪除乙個可愛的節點,那肯定是將其先變成葉子節點。查詢這個節點的前驅後繼,將前驅旋轉到根,後繼旋轉到成為前驅的兒子,這個時候,目標節點就一定是後繼節點的左兒子並且是葉子節點。那麼就搞死它啦!x)
while(1
)
else
else
return
t[u].v;}}
}
void delete(int x)//完結撒花!刪除x
else
t[next].ch[
0]=0;//
這個節點直接丟掉(不存在了)
}//引用自yyb大佬
蒟蒻林蔭小複習 K短路的A 解法
看標題都知道講的是什麼,但為什麼特指是a 關於k短路的解法呢?因為林蔭不會其他的。能看到這篇部落格的估計也都知道k短路和a 分別是什麼了吧,下面只介紹一下估價函式 由於林蔭並沒有經過學術訓練,所以一下關於a 的理解均為感性,僅可作為oier速成知識點時的一點資料,切莫作為演算法學術依據。先思考一下,...
蒟蒻林蔭小複習 克魯斯卡爾重構樹
這是乙個冷門到不能再冷門的東西,至於這東西有什麼用,且聽我慢慢道來。現在給定一張無向圖,每個點有乙個點權,每條邊有乙個邊權。現在給出許多詢問三元組 x,y,z 要求求出從x出發,只能走邊權不超過y的邊,所能走到邊權第z大的點的點權是多少?bzoj3551 如果離線的話,大佬們好像可以用主席樹套樹之類...
蒟蒻複習之 Floyd
暴力無解演算法 入門必備 然而我發現這個簡單的演算法還有很多用法 作為複習篇不講原理 圖的要求 既可以是無向圖也可以是有向圖,邊權可以為負,但是不能存在負環 複雜度為o n 3 原理 dp思路 f i j f i k f k j void floyd 注意 1應對所建的圖進行初始化如下 void i...