主席樹學習筆記

2022-08-28 14:45:23 字數 1340 閱讀 8140

主席樹又名可持久化線段樹,即可以儲存線段樹的歷史版本,比如得到第k次操作後的值這樣的命令。

我們看一顆線段樹:

對於這顆線段樹我們進行q次單點修改,要你求第k次的線段樹是什麼樣的,那麼很明顯,我們最簡單的是建立q顆線段樹,假設該線段樹有n個節點,我們一般開線段樹大小是n*4,那麼總空間利用就是q*n*4,很明顯不行,那麼我們再觀察一下,其實每次修改的時候只有一條鏈被改變了,也就是這條鏈就是第i次修改所改變的東西,那麼我們乙個個記錄鏈,這樣的話每條鏈長度為logn,空間複雜度就是q*logn,比剛才好了不知道多少!然後對於每條鏈要記錄他的子節點(有的話),以及和他相連的點裡沒改變的,比如下面這個圖(假設改變e點):

e`,b`,a`就是改變的的值,然後你按照以a`為根開始往下跑相連的點,此時記錄的也確實是第1次修改以後的樹,也就是說對沒修改的點實行共用策略,這就是一顆對字首建立的樹!!!!下面看**:

這題是:

轉    自:

#include#include#include#include#define mid ((l+r)/2)

#define c(a, b) memset(a, b, sizeof(a))

using namespace std;

const int n=100007;

const int inf=0x3f3f3f3f;

int n, m, a[n], x, y, k;

vectore;

void read(int &x)

while(s>='0'&&s<='9')

x*=f;

}int getid(int x)

struct no t[n*40];    ///一般對於一顆線段樹開2qlogn的陣列大小

int cnt, root[n];

void update(int l, int r, int &x, int y, int pos)

if(mid>=pos)else

}int query(int l, int r, int x, int y, int k)

int sum=t[t[y].l].sum-t[t[x].l].sum; ///得到y-x+1區間線段樹的真正的和

if(sum>=k)else

}int main( )

}return 0;

}

主席樹學習筆記

問題 給定乙個n個數的序列,q次詢問第x個數到第y個數中的第k最值。我們假定是第k小。為了使討論更加簡便,我們假定序列的每個數都是不大於n的正整數。當然一般題目中元素範圍很大,但是可以用離散化預處理來做到這一點。考慮乙個比較高階的做法 令g i j 為前i個數中,值為j的數的個數。很容易用o n 2...

主席樹 學習筆記

主席樹就是權值線段樹的乙個集合 模板題為求某個區間的第 k 大,權值線段樹也有求第 k 大這個功能,但是不能維護區間,只能求整個全域性第 k 大 所以學習這個之前,務必先搞懂權值線段樹 所以 都是這道題的 模板 可持久化線段樹 1 主席樹 1 先從建樹開始說起 int build int l,int...

主席樹學習筆記

學習博文 主席樹總結 p3834 模板 可持久化線段樹 2 主席樹 給出乙個序列,每次詢問給定區間內第k小的值。主席樹模板。考慮最簡單的情況,也就是查詢區間固定。首先對資料進行離散化,用線段樹維護。每個節點對應離散化後值域的數的總個數 size.從上到下進行查詢時,判斷當前節點左子樹的 size 和...