线段树-Count on a Treap-神题
Count on a Treap
題目來(lái)源
Codechef Feb 2014 COT5
https://www.codechef.com/problems/COT5
問(wèn)題提出
什么是Treap
- 是一顆二叉搜索樹(shù),每個(gè)節(jié)點(diǎn)擁有keykeykey屬性.
- 是一顆堆,每個(gè)節(jié)點(diǎn)擁有weightweightweight屬性
問(wèn)題
- nnn次操作,三種類(lèi)型,要求維護(hù)"大根Treap"
- (0,k,w)(0,k,w)(0,k,w) ,插入keykeykey為k,weightk,weightk,weight為www的點(diǎn).
- (1,k)(1,k)(1,k),刪除keykeykey為kkk的點(diǎn)
- (2,ku,kv)(2,k_u,k_v)(2,ku?,kv?),詢問(wèn)keykeykey為ku,kvk_u,k_vku?,kv?的兩點(diǎn)在TreapTreapTreap中的距離.
保證keykeykey,weightweightweight均不相同.
問(wèn)題解答
dist(u,v)=dep(u)+dep(v)?2?dep(lca)dist(u,v) = dep(u) + dep(v) - 2* dep(lca)dist(u,v)=dep(u)+dep(v)?2?dep(lca)
我們以keykeykey為下標(biāo),將這個(gè)樹(shù)按中序遍歷展開(kāi).
顯然[ku,kv][k_u,k_v][ku?,kv?]之間最大的weightweightweight最大的點(diǎn)就是兩點(diǎn)的lcalcalca.
證明:首先lcalcalca一定在區(qū)間[ku,kv][k_u,k_v][ku?,kv?]之間,不然ku,kvk_u,k_vku?,kv?將位于lcalcalca的同一側(cè),這不可能.其次權(quán)重最大的點(diǎn)一定是這顆子樹(shù)的根節(jié)點(diǎn),這個(gè)點(diǎn)一定是祖先,如果它不是lcalcalca的話,那么它的keykeykey將大于或小于lcalcalca形成的子樹(shù)中所有的點(diǎn)的keykeykey,也就是說(shuō)它不在區(qū)間[ku,kv][k_u,k_v][ku?,kv?]之間,矛盾.
至此,用線段樹(shù)可以輕松維護(hù)lcalcalca.
那么如何維護(hù)一個(gè)點(diǎn)在樹(shù)上的深度呢?
根據(jù)Treap的特殊性質(zhì),我們知道每個(gè)點(diǎn)的weightweightweight一定小于他父親的weightweightweight.
從這個(gè)點(diǎn)到根節(jié)點(diǎn)的祖先鏈上的weightweightweight是不斷遞增的.
這里有一個(gè)非常特殊的性質(zhì),在序列上就是從這個(gè)點(diǎn)往兩側(cè)各找一個(gè)直接的遞增子序列,那么序列上的點(diǎn)都是他的祖先.
這個(gè)性質(zhì)基于這樣一個(gè)事實(shí):每個(gè)點(diǎn)左右兩側(cè)的第一個(gè)大于它weightweightweight的點(diǎn),都是這個(gè)點(diǎn)的一個(gè)祖先.因?yàn)槠渲幸粋€(gè)點(diǎn)是它的父親,而另一個(gè)點(diǎn)…自己畫(huà)圖觀察一下就好了.
因此兩個(gè)遞增序列的長(zhǎng)度和就是它到根的距離.
如何維護(hù)某一個(gè)點(diǎn)向右的直接遞增序列呢.也是使用線段樹(shù),參考我的另一篇博客,樓房重建.
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的线段树-Count on a Treap-神题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 线段树-Chossing Ads-分治,
- 下一篇: 线段树-楼房重建-洛谷-P4198