深度剖析主席樹(靜態)

2021-09-01 02:12:32 字數 1544 閱讀 8431

主席樹(chairman tree)(據說是被chairman傳開的)

它是一種專門用來實現求區間第k大這類操作的資料結構

q:這不是分塊輕鬆解決的事嗎?

a:是的,但是分塊時間為

q:這是不是很難,**複雜度極高?

a:nonono,**複雜度一點都不高,前置知識只有動態開點線段樹

q:那我不會怎麼辦?

a:右**行度娘,或者菜雞的部落格

菜雞很菜,剛學了主席樹,還是最簡單的靜態

首先思考一下,區間求第k大,最暴力的解自然是每次排序,是

q:如果用資料結構維護呢?

a:每次詢問用一棵權值線段樹或者權值樹狀陣列+二分維護,也是,qaq,(不會可見可憐的狗狗這道題)

權值樹狀陣列+二分姑且不論,我們只談權值線段樹(時間複雜度低才是王道)

每次詢問的是一段區間,與區間相關的演算法沒有多少,也就字首和,線段樹……

權值線段樹下標記的是值的大小,存的是出現次數,所以具有可加減性

故選用字首和

前面的引導就差不多結束了,進入正文了

主席樹=字首和+線段樹=對每個字首和中的點開一棵權值線段樹(下標記的是權值的線段樹)

線段樹上的結點記錄

建立每次只用新插入乙個結點,

如果該結點應該在左子樹,右子樹就不用變;反之左子樹不用變

每次新插入只用

void add(int &p,int l,int r,int x)

//lc為左兒子,rc為右兒子,s為結點個數

查詢:由於上文提到線段樹具有可減性,只用在(不會可見可憐的狗狗這道題,也可以看**)

int kth(int p1,int p2,int l,int r,int x)

總結:主席樹就是字首和+線段樹的思想毒瘤了一點(有心人可以看出我上面的引導是倒推的),但是只要你熟練掌握線段樹,知道思想後小菜一碟

例題(時刻更新)

1、luogu p3834 【模板】可持久化線段樹 1(主席樹)

額,模板題,加個離散化就號了

#include#includeusing namespace std;

const int n=4e6+5;

int n,m,rt[n],b[n];

struct aa[n];

bool cmp(a x,a y)

int kth(int p1,int p2,int l,int r,int x)

}zxs;

int main()

return 0;

}

2、可憐的狗狗(這是超連結)

模板題*2

3、luogu p3919 【模板】可持久化陣列(可持久化線段樹/平衡樹)

模板題*3

4、bzoj 2223: [coci 2009]patuljci

模板題,查詢中位數相同的是否超過序列長度的一半

靜態主席樹

首先主席樹解決什麼樣的問題?最經典的問題就是 區間第k小問題 也就是指定乙個區間,要求求出這個區間中第k小的數字 在搞懂什麼是主席樹之前,我們要先對權值線段樹有一定的了解,下面我們就先說一下權值線段樹,然後詳細說一下主席樹以及主席樹程式的實現.權值線段樹 每個葉子節點的數值表示的是 陣列中含有這個數...

靜態主席樹

主席樹 對於序列的每乙個字首建一棵以序列裡的值為下標的線段樹 所以要先離散化 記錄該字首序列裡出現的值的次數 記離散後的標記為1 n 下面值直接用1 n代替 對於區間 x,y 的第k大的值,那麼從root x 1 root y 開始,t root y 1,mid root x 1 1,mid t表示...

主席樹 靜態 的輕鬆入門

n i 1 85 kj 0i2 i 1n 58 j 0ki2 emmm 最近入門了主席樹,感覺其實不是很難,主要理解了就很簡單了 畢竟 這麼短 給出乙個數列,求區間 l r 之間的第 k 大值利用數列中 n 個資料建立 n 棵樹,其中第 i 棵樹維護 1 i 這個字首內的資料資訊 第 i 棵樹中的每...