靜態主席樹(區間第k小) 洛谷P3834

2022-05-22 19:21:12 字數 2328 閱讀 1767

時間限制1.00s ~ 1.20s

記憶體限制125.00mb ~ 250.00mb

這是個非常經典的主席樹入門題——靜態區間第k小

資料已經過加強,請使用主席樹。同時請注意常數優化

如題,給定n個整數構成的序列,將對於指定的閉區間查詢其區間內的第k小值。

第一行包含兩個正整數n、m,分別表示序列的長度和查詢的個數。

第二行包含n個整數,表示這個序列各項的數字。

接下來m行每行包含三個整數l,r,k , 表示查詢區間l,r]內的第k小值。

輸出包含k行,每行1個整數,依次表示每一次查詢的結果

輸入 

5 5

25957 6405 15770 26287 26465

2 2 1

3 4 1

4 5 1

1 2 2

4 4 1

輸出

6405

15770

26287

25957

26287

資料範圍:

對於20%的資料滿足:1≤n,m≤10

對於50%的資料滿足:1≤n,m≤10^3

對於80%的資料滿足:1≤n,m≤10^5

對於100%的資料滿足:1≤n,m≤2⋅10^5

對於數列中的所有數a_iai​,均滿足−10^9≤ai​≤10^9

樣例資料說明:

n=5,數列長度為5,數列從第一項開始依次為[25957,6405,15770,26287,26465]

第一次查詢為[2,2]區間內的第一小值,即為6405

第二次查詢為[3,4]區間內的第一小值,即為15770

第三次查詢為[4,5]區間內的第一小值,即為26287

第四次查詢為[1,2]區間內的第二小值,即為25957

第五次查詢為[4,4]區間內的第一小值,即為26287

這是一題很經典的靜態主席樹,對於主席樹而言,其實它就是可持續化線段樹與權值線段樹的結合體而已。

其核心就是update的可持續化過程與query的權值線段樹詢問過程:

int update(int l,int r,int pos,int

per)

if (mid>=pos) lson[rt]=update(l,mid,pos,lson[per]);

else rson[rt]=update(mid+1

,r,pos,rson[per]);

//sum[rt]=sum[lson[rt]]+sum[rson[rt]];

return

rt;}

該update程式段解釋入下: 

如上圖所示,第一次修改時只會經過紅色部分,那麼也就是說,沒有經過的點保持原來的節點編號,經過的節點另開空間(和動態開點一樣)同時編號增加。

我們可以先將當前節點的左右兒子編號賦值為上乙個版本的當前節點的左右兒子編號,然後要修改的時候直接覆蓋就好了。

2——和線段樹一樣,我們在他更新到葉子節點的時候再更新,最後加乙個push_up就好了

int query(int l,int r,int l,int r,int

k)

該query程式段解釋如下:

我們可以構想一下,先在左子樹中找,如果左子樹的sum大於k也就是說,該區間存在第k小的數在左子樹中,那麼我們就在左子樹中找,否則就存在右子樹中,我們在右子樹中找,同時傳入k-左子樹的sum。那麼**也就出來了。

以下是ac**:

#include using

namespace

std;

const

int mac=2e5+10

;int a[mac],sum[mac<<6],lson[mac<<6],rson[mac<<6

];int tot=0

,b[mac],ver[mac];

int build(int l,int

r)int update(int l,int r,int pos,int

per)

if (mid>=pos) lson[rt]=update(l,mid,pos,lson[per]);

else rson[rt]=update(mid+1

,r,pos,rson[per]);

//sum[rt]=sum[lson[rt]]+sum[rson[rt]];

return

rt;}

int query(int l,int r,int l,int r,int

k)void

in(int &x)

intmain()

while (m--)

return0;

}

主席樹 靜態區間第k小

這是個非常經典的主席樹入門題 靜態區間第k小 資料已經過加強,請使用主席樹。同時請注意常數優化 如題,給定n個整數構成的序列,將對於指定的閉區間查詢其區間內的第k小值。輸入格式 第一行包含兩個正整數n m,分別表示序列的長度和查詢的個數。第二行包含n個整數,表示這個序列各項的數字。接下來m行每行包含...

主席樹(區間第k小)

k th number 求區間內第k小的數。主席樹的板子題 主席樹左子樹存小值,右邊大值,用sum記錄一下子樹節點個數。對 l,r 的查詢區間,root r root l 1 可得出 l,r 的差值,也就是大小的個數 include include include include include i...

主席樹 區間第k小

主席樹 權值線段樹 可持久化 權值線段樹 在此處指各個數字在某個區間內出現的次數 那麼第一棵權值線段樹會記錄 1,1 的數字出現次數 第n棵權值線段樹會記錄 1,n 的數字出現次數 例 數列為110001 第一棵權值線段樹記錄為tree1 0 0 tree1 1 1 第二棵權值線段樹記錄為tree2...