主席樹是最經典的可持久化資料結構之一,用於查詢歷史版本的資訊,主要需要用到字首和思想(未必),今有以下二模板題,請與君共賞之.
大意求靜態區間第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 和...