主席樹學習筆記

2022-08-18 23:15:18 字數 2956 閱讀 2631

主席樹是最經典的可持久化資料結構之一,用於查詢歷史版本的資訊,主要需要用到字首和思想(未必),今有以下二模板題,請與君共賞之.

大意求靜態區間第k小.

主要思想:

利用主席樹字首和思想,對序列先離散得序列$$,然後第$i$個版本的主席樹表示區間$[1,i]$上各個元素出現的次數.先建顆空樹,一一插入,每次update繼承原版本的節點資訊,rt[i]用以記錄區間[1,i]的線段樹根作為入口,然後根據需求進行單點修改即可.$sum$可以看作字首和,當我們要查詢$[x,y]$上的各元素出現次數,可以用區間$[1,y]$與區間[1,x-1]作差,然後根據需求統計答案即可.

code:

#include#include

#include

#include

#include

#include

#include

#define r register

#define debug puts("mlg")

#define next exjfasaslfasfadfsaf

#define maxn 210000

using

namespace

std;

typedef

long

long

ll;typedef

long

double

ld;typedef unsigned

long

long

ull;

inline ll read();

inline

void

write(ll x);

inline

void

writesp(ll x);

inline

void

writeln(ll x);

ll n,m;

ll a[maxn],b[maxn],rt[maxn

<<5],ls[maxn<<5],rs[maxn<<5],sum[maxn<<5

],cnt;

ll p;

inline

void build(ll &rt,ll l,ll r)

inline ll update(ll fa,ll l,ll r)

inline ll query(ll u,ll v,ll l,ll r,ll k)

ll q;

intmain()

while(m--)

} inline ll read()while(ch>='

0'&&ch<='

9')return x*t;}

inline

void write(ll x)if(x<=9)write(x/10);putchar(x%10+'0'

);}inline

void writesp(ll x)

inline

void writeln(ll x)

大意:今有一串行與若干操作.操作細分二種,其一為修改某歷史版本某位置值作為新版本,其二為查詢某歷史版本某位置值並copy該版本作為新版本,試問每次查詢輸出數有幾何.

solution:

此題較容易,不必利用字首和思想,無需離散,修改正常改,查詢正常查,新版本直接使新根與該版本根相同即可.

code:

#include#include

#include

#include

#include

#include

#include

#define r register

#define next bmdsaljdk

#define debug puts("mlg")

#define maxn 1100000

using

namespace

std;

typedef

long

long

ll;typedef

long

double

ld;typedef unsigned

long

long

ull;

inline ll read();

inline

void

write(ll x);

inline

void

writeln(ll x);

inline

void

writesp(ll x);

ll n,m;

ll a[maxn],ls[maxn

<<5],rs[maxn<<5],num[maxn<<5],cnt,rt[maxn<<5

];ll tot;

inline

void build(ll &rt,ll l,ll r)ll mid=l+r>>1;build(ls[rt],l,mid);build(rs[rt],mid+1

,r);}

inline ll update(ll fa,ll l,ll r,ll p,ll q)ll mid=l+r>>1;if(p<=mid) ls[rt]=update(ls[rt],l,mid,p,q);else rs[rt]=update(rs[rt],mid+1,r,p,q);return

rt;}

inline ll query(ll v,ll l,ll r,ll p)

intmain()

else

}}inline ll read()while(ch>='

0'&&ch<='

9')return x*t;}

inline

void write(ll x)if(x<=9)write(x/10);putchar(x%10+'0'

);}inline

void writesp(ll x)

inline

void writeln(ll x)

主席樹學習筆記

問題 給定乙個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 和...