主席樹入門題

2021-08-20 10:10:56 字數 4853 閱讀 3985

全稱是可持久化權值線段樹(以前一直分不清可持久化線段樹和主席樹的區別)

但實際上寫法跟可持久化trie沒什麼區別,維護權值就ok了

那就不講了

description

jz擁有乙個很大的野生動物園。這個動物園坐落在乙個狹長的山谷內,這個區域從南到北被劃分成n個區域,每個區域都飼養著一頭獅子。這些獅子從北到南編號為1,2,3,…,n。每頭獅子都有乙個覓食能力值ai,ai越小覓食能力越強。飼養員西西決定對獅子進行m次投喂,每次投喂都選擇乙個區間[i,j],從中選取覓食能力值第k強的獅子進行投喂。值得注意的是,西西不願意對某些區域進行過多的投喂,他認為這樣有悖公平。因此西西的投喂區間是互不包含的(即區間[1,10]不會與[3,4]或[5,10]同時存在,但可以與[9,11]或[10,20]一起)。同一區間也只會出現一次。你的任務就是算出每次投喂後,食物被哪頭獅子吃掉了。

input

覓食能力值。(1<=能力值<=maxlongint)。此後m行,每行描述一次投喂。第t+2的三個數i,j,k表示在第t次投喂中,西西選擇了區間[i,j]內覓食能力值第k強的獅子進行投喂。

output

輸出檔案有m行,每行乙個整數。第i行的整數表示在第i次投喂中吃到食物的獅子的覓食能力值。

sample input

7 2

1 5 2 6 3 7 4

1 5 3

2 7 1

sample output 3 2

data constraint

hint

對於100%的資料,有1<=n<=100000,1<=m<=50000。

區間第k大……標準的主席樹例題

維護每個範圍內數的個數,然後[r]-[l-1],樹上二分查詢

#include 

#include

#include

#define fo(a,b,c) for (a=b; a<=c; a++)

#define fd(a,b,c) for (a=b; a>=c; a--)

#define mx 2147483647

using namespace std;

inttr[5000001][3];

int n,i,j,k,l,r,q,s,len;

void new(int t,int

x)void change(int t,long long l,long long r,int

x) else

}void find(int t,int t,long long l,long long r,int

s) if (tr[tr[t][1]][0]-tr[tr[t][1]][0]>=s)

find(tr[t][1],tr[t][1],l,mid,s);

else

find(tr[t][2],tr[t][2],mid+1,r,s-(tr[tr[t][1]][0]-tr[tr[t][1]][0]));

}int main()

for (;q;q--)

return

0;}

description

有乙個長度為n的陣列。m次詢問,每次詢問乙個區間內最小沒有出現過的自然數。

input

第一行n,m。

第二行為n個數。

從第三行開始,每行乙個詢問l,r。

output

一行乙個數,表示每個詢問的答案。

sample input

5 52 1 0 2 1

3 32 3

2 41 2

3 5

sample output

1data constraint

對於30%的資料:

1<=n,m<=1000

對於100%的資料:

1<=n,m<=200000

0<=ai<=10^9

1<=l<=r<=n

維護每個範圍內的數出現次數,之後二分+奇怪剪枝

如果左區間內的數出現次數《區間長度,那麼就一定在左區間,否則都有可能

(實際就是暴力)

#include 

#include

#include

#define fo(a,b,c) for (a=b; a<=c; a++)

#define fd(a,b,c) for (a=b; a>=c; a--)

#define min(x,y) (x#define mx 2147483647

using namespace std;

inttr[10000001][3];

int n,i,j,k,l,r,q,s,len,ans;

void new(int t,int

x)void change(int t,long long l,long long r,int

x) else

}void find(int t,int t,long long l,long long r)

find(tr[t][1],tr[t][1],l,mid);

if (ans<123456789) return;

if (tr[tr[t][1]][0]-tr[tr[t][1]][0]>=r-mid)

find(tr[t][2],tr[t][2],mid+1,r);

}int main()

for (;q;q--)

return

0;}

維護到當前位置時區間內的值出現的min(最右位置)

然後乙個二分(從r開始),如果區間內所有數的最右位置都≥l以內就在右邊,否則在左邊

話說我還想過建10^9棵線段樹

#include 

#include

#include

#define fo(a,b,c) for (a=b; a<=c; a++)

#define fd(a,b,c) for (a=b; a>=c; a--)

#define min(x,y) (x#define mx 2147483647

using namespace std;

inttr[10000001][3];

int n,i,l,r,q,s,len;

void new(int t,int

x)void change(int t,long long l,long long r,int

x) if (x

<=mid)

else

tr[t][0]=min(tr[tr[t][1]][0],tr[tr[t][2]][0]);

}void find(int t,long long l,long long r,int

s) if (tr[tr[t][1]][0]find(tr[t][1],l,mid,s);

else

find(tr[t][2],mid+1,r,s);

}int main()

for (;q;q--)

return

0;}

description

在組合遊戲中計算狀態的 sg 值時,我們常常會遇到 mex 函式。mex(s) 的值為集合 s 中沒有出現過的最小自然數。例如,mex() = 0、mex() = 4。

給定長度為 n 的序列 a。現有 m 次詢問,每次給定 l 和 r,詢問區間 [l,r] 的數構成的集合的 mex 值。

input

輸入資料的第一行包含三個整數 n、m 和 t,其中 t 為 0 或者 1,表示資料型別。

接下來一行,包含 n 個非負整數,為序列 a。

接下來 m 行,每行描述乙個詢問。第 i 行包含兩個正整數 l 和 r,代表第 i 次詢問的區間的左右端點。如果 t = 1,則詢問進行了加密,從第二個詢問開始,讀入的 l 和 r 異或前一次詢問的答案才是真正的詢問左右端點。

output

對於每個詢問,輸出一行,代表詢問區間的 mex 值。

sample input

5 4 0

2 1 0 2 1

3 3

2 3

2 4

1 2

sample output

1 2 3 0

#include 

#include

#include

#define fo(a,b,c) for (a=b; a<=c; a++)

#define fd(a,b,c) for (a=b; a>=c; a--)

#define min(x,y) (x#define mx 2147483647

using namespace std;

inttr[10000001][3];

int n,i,l,r,q,s,len,size,ans;

void new(int t,int

x)void change(int t,long long l,long long r,int

x) if (x

<=mid)

else

tr[t][0]=min(tr[tr[t][1]][0],tr[tr[t][2]][0]);

}void find(int t,long long l,long long r,int

s) if (tr[tr[t][1]][0]find(tr[t][1],l,mid,s);

else

find(tr[t][2],mid+1,r,s);

}int main()

for (;q;q--)

fclose(stdin);

fclose(stdout);

return

0;}

主席樹 入門

思想類似字首和,訪問某狀態的線段樹可通過末減初狀態進行求解。hdu4417 第二道模板題 有很多細節需要注意。1.題目給定ai的高度可能為0,但通過離散化事實上不影響結論。2.給定的訪問區間 x,y 以及高度h也可能為零,因而x,y需對應 查詢依舊是root y root x 1 3.對於高度h,為...

主席樹入門

推薦部落格 早在很久之前就聽過主席樹這個名詞,不過一直沒有去學,當時想的是先把線段樹學明白了,今天想學這個是因為一場 cf。主席樹其實就是由 n 棵權值線段樹組成,並且你要保留著 i 棵線段樹的根節點,這 i 棵線段樹其實就可以看成是不同的歷史的版本,現在如果想讓我們查詢某一段區間時,我們直接做差就...

Just h index(主席樹裸題)

just h index 題意 輸入第一行給了 n q 代表有 n 個數 q 次詢問,第二行給出這 n 個數,每次詢問乙個區間,答出乙個最大的數 h 使得這個區間裡大於等於 h 的數的個數大於等 h 題解 見 吧,比較好理解的,主席樹 ac code 1 主席樹是多個權值線段樹 2 include ...