可持久化線段樹 專題 AbandonZHANG

2022-05-29 12:15:08 字數 1811 閱讀 8568

可持久化線段樹(函式式線段樹):

可持久化資料結構(persistent data structure)就是利用函式式程式設計的思想使其支援詢問歷史版本、同時充分利用它們之間的共同資料來減少時間和空間消耗。

所以這裡講的可持久化線段樹也叫函式式線段樹(又叫主席樹……因為先驅就是fotile主席orz……)。偶還是比較喜歡叫它函式式線段樹。

兩篇**:

《範浩強_wc2012談談各種資料結構》  ---範浩強

《可持久化資料結構研究》          ---陳立傑

ooooorrrzz…………

兩篇部落格:

很詳細的介紹了函式式線段樹(主席樹)。

主席親筆啊 orz……

反正大體的思想就是只賦值不修改,儲存歷史版本------每次加入新結點後都返回一顆包含新結點的新樹儲存起來(什麼?這麼多樹空間消耗太太太大?------充分利用歷史版本)

可用函式式線段樹做的題目:poj2104;  spoj cot,cot2,cot4;  bzoj 1901(zju 2112);  bzoj2653;  hdoj 4417; hdoj4348。

♣poj 2104 k-th number

(hdu 2665

)(不帶修改的區間第k小值)

首先來看  線段樹找第k小:假設數是在(0,n)之間的,對權值建一顆線段樹,每個節點用cnt表示這個權值上的數的個數。那麼考慮在當前節點t內找t節點內的第k小。如果t的左兒子上數的個數cnt已經大於k,那麼第k小一定在左兒子中,所以就在左兒子中找第k小數。否則,答案就是在右兒子中找第k-cnt(leftson)小的數。

現在來考慮區間第k小。直接用上面的方法顯然是不行的,因為可能區間和節點會有交叉(區間一部分佔乙個節點的一部分,另一部分佔另乙個節點的一部分)。

預備知識:兩顆結構相同的權值線段樹a,b,權值線段樹a(+/-)b的每個節點的cnt值就是對應權值線段樹a的cnt值減去b的cnt值。那麼對於權值線段樹a-b,我們想對它查詢並不需要建出它,只需要在a、b中對應的位置分別維護即可。

#include #include #include #include #include #include #include #include #include #include #include #define mid(x,y) ((x+y)>>1)

using namespace std;

const int maxn = 100010;

struct tree

t[maxn*20];

int tot,root[maxn];

int build(int l, int r)

int change(int o, int x, int v)

int query(int n,int o,int k) //詢問區間[t1,t2]第k小

int b[maxn],sortb[maxn];

int q;

int main()

for (int i = 0; i < m; i ++)

}return 0;

}

ps: 這個可以歸納為一類問題 --> 當我們在權值線段樹上可以完成某些對整個區間的操作而對子區間無力時,可以用這種函式式線段樹的轉換方法來完成,但需要滿足乙個條件:線段樹中儲存的資料要支援區間減法(就是諸如區間[l,r]可以通過區間[1,r] - [1,l-1]來算出)。我曾想過用這種函式式線段樹的方法做hdu 4358

,結果寫完除錯發現不對就是因為那題不滿足區間減法。。。囧。當然我還是覺得函式式線段樹是可以做那題的,只不過我對這個還不太深入掌握(說白了就是能力捉雞t_t。。。)

可持久化線段樹總結(可持久化線段樹,線段樹)

最近正在學習一種資料結構 可持久化線段樹。看了網上的許多部落格,弄了幾道模板題,思路有點亂了,所以還是來總結整理下吧。你需要維護這樣的乙個長度為 n 的陣列,支援如下幾種操作 在某個歷史版本上修改某乙個位置上的值 訪問某個歷史版本上的某一位置的值 此外,每進行一次操作 對於操作2,即為生成乙個完全一...

可持久化線段樹

可持久化線段樹,意思是可以查詢歷史記錄的線段樹。又叫主席樹。我們可以通過記錄不同的根節點,並在每乙個更新到的節點處新建必要的節點。詢問不同版本的主席樹,只需要進入不同的根節點即可。例題 給定n,m,輸入n個數組成的數列,有m個詢問,每次詢問l,r這個區間中,第k小的數的值。分析 這個題可以巧妙運用主...

可持久化線段樹

以p3919 模板 可持久化陣列 可持久化線段樹 平衡樹 為例。知識點 1.練習可持久化線段樹 2.線段樹維護數列。線段樹維護數列單點查詢僅需o logn 3.記得return root 4.記得設定左右兒子 5.有時需注意cnt的初始大小 include using namespace std i...