前言
呃,首先宣告,看這篇部落格前,最好先去學一學主席樹,畢竟可持久化陣列的實現是完全基於主席樹的(那些亂七八糟的玄學演算法請走開)。
順便吐槽一句,可持久化陣列這個名字聽起來真的很智障。 簡介l in
klink
link
主席樹詳見部落格可持久化專題(一)——**主席樹:可持久化線段樹
可持久化陣列支援單點修改和單點查詢。
.單點修改和單點查詢這種東西不是直接陣列就能解決了嗎?幹嘛要可持久化?
因為要用到歷史版本啊!
基本思路
思路1:我們可以考慮對每乙個版本開乙個陣列,這就是最暴力的打法了,這樣顯然會mle+tle。
思路3:雖然思路2會炸飛,但是,它顯然比思路1更容易優化。看到一群線段樹,我們很容易想到用可持久化線段樹——主席樹來優化它。
具體實現
在這裡,主席樹的作用就不是查詢區間第k
kk大了,而是在每乙個葉子節點上記錄當前版本這一位上的值。
如果你主席樹打得夠熟練,這就是一道水題了,直接上**吧:(還是洛谷上的一道板子題)
#include
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define ll long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (a==b&&(b=(a=ff)+fread(ff,1,100000,stdin),a==b)?eof:*a++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define n 1000000
int pp_=0;
char ff[
100000],
*a=ff,
*b=ff,pp[
100000];
using
namespace std;
int n,q,tot=
0,rt[n+5]
,a[n+5]
;struct chairman_tree
node[n*20]
;inline
void
read
(int
&x)inline
void
write
(int x)
inline
void
build
(int
&rt,
int l,
int r)
//初始的建樹,在這道題中,除了動態開點以外與線段樹完全一樣
build
(node[rt]
.son[0]
,l,mid)
,build
(node[rt]
.son[1]
,mid+
1,r);}
inline
void
newpoint
(int
&rt,
int lst,
int l,
int r,
int x,
int val)
//新建乙個版本
if(x<=mid)
newpoint
(node[rt]
.son[0]
,node[lst]
.son[0]
,l,mid,x,val)
;else
newpoint
(node[rt]
.son[1]
,node[lst]
.son[1]
,mid+
1,r,x,val);}
inline
intquery
(int rt,
int l,
int r,
int x)
//詢問某一版本某一位上的值
intmain()
return
fwrite
(pp,
1,pp_,
stdout),
0;}
可持久化專題
一切之始主席樹 可持久化並查集 首先可持久化並查集我們是用主席樹來維護的,葉子節點維護每個位置的fa 維護2個量 每個點的父親和每棵樹的根節點的高度。那麼不使用路徑壓縮的話這個版本的主席樹和上個版本的主席樹 有且只有乙個點會被改動。那麼就可以進行可持久化了。既然取消了路徑壓縮,為了保證複雜度,我們需...
可持久化專題(三) 可持久化並查集
前言 要學可持久化並查集,必須先會可持久化陣列。l in klink link 可持久化陣列詳見部落格可持久化專題 二 可持久化陣列的實現 簡介 可持久化並查集應該是乙個挺實用的資料結構 例如noi2018day1t1中就有它的身影 它主要建立於可持久化陣列的基礎之上 而可持久化陣列的實現是完全基於...
可持久化陣列
日常不想放題目 luogu p3919 模板 可持久化陣列 題目中要求可以查詢歷史狀態,最暴力的想法是開 a m n 的二維陣列,每次修改暴力複製並修改,每次查詢暴力掃瞄,時間複雜度是 o m n 的,但這顯然是不行的.這個時候其實很容易想到線段樹,但線段樹維護的是當前狀態而無法維護歷史狀態,一種暴...