問題
主席樹、可持久化線段樹、動態開點線段樹指向的都是同一類問題。即給定一個序列,求與等級、名次相關的答案,常用線段樹計數加減的方式解決,在需要的時候也可以對等級、名次對應的數值離散化,前提是沒有修改或允許離線操作
算法原理
為了解決此類問題,需要對每個序列節點建一棵以詢問目標大小為值域的線段樹,每一棵線段樹都有一個它對應的前驅線段樹,並成為此前驅的擴展和延伸。
例如(poj2104 kth number),對於求解區間第k大(小)問題,對給定的整個序列的每個點建權值線段樹,樹的值域可以是離散化或非離散化后的點的數值的值域,線段樹維護一個size域,即在序列1~i中出現的在數值區間[l,r]中的數的個數,因此每個任意點i的線段樹的前驅線段樹就是點i-1的線段樹,因此每棵線段樹可以看作一個前綴和的處理。若要處理序列區間[a,b]的區間第k大(小),把線段樹(b)和線段樹(a-1)的權值和相減就可以得出序列區間的權值和了。
例如(bzoj2588 count on a tree),對於求解樹上第k大(小)問題,可以解構整棵樹,用倍增或樹鏈剖分或dfs序處理整棵樹(甚至是森林),那么,我們就要對每個節點建權值線段樹,此時的前綴和就是根節點到該子節點的權值前綴和了。要注意,這里求解節點u到v的權值第k大,即求解線段樹(u)+線段樹(v)-線段樹(lca(u,v))-線段樹(fa(lca(u,v)))。
時間復雜度大概都是O(n * log2 (len))的,空間復雜度理論上也是O(n * log2 (len)),但是如果是用靜態存儲池來開點一般要開兩倍的空間,動態的話就不說了,那很容易re。
算法應用
此類數據結構可以解決名次類的靜態乃至動態的區間型問題,如第k大、中位數乃至樹上的問題