最近一直在搞資料結構,主席樹,理解也不算特別深刻,還沒有對動態開點和可持久化思想理解特別深刻,所以,今天我就準備寫一篇可持久化陣列來通一通腦子新手入門題目:洛谷:可持久化陣列
就題論題:
給乙個陣列a[ ]:
我們可以對其進行修改,然後詢問不同版本的值,最初的版本為:0,修改一次就產生乙個新版本
樸素做法:
寫乙個二維陣列首先:我們建出最初版本的線段樹來存版本0的陣列,我們以陣列大小為5為例:ver[i][j]
i
代表版本,然後尋問 第i
個版本第pos
個位置的值,這樣對於小資料來說還行,不會mle
,也不會tle
,但是對於大資料來說,每次修改都是o(n)
,修改m
次,時間複雜度為o(nm)
,而且大資料會mle,ver[10^6][10^4]
毫無疑問陣列存不下,那麼現在可持久化陣列出現了,可持久化陣列的實現利用了線段樹+可持久化思想
根據上圖,已經把圖建了出來了,也不怎麼耗費空間了,我們要查某乙個版本的陣列的值,只需要,知道某一版本的根節點即可ac**:
#include
.h>
using namespace std;
//可持久化陣列
const
int maxn=
1e6+5;
int root[maxn]
;struct node
tr[maxn*40]
;int a[maxn]
;int cnt;
void
build
(int l,
int r,
int&now)
int mid=l+r>>1;
build
(l,mid,tr[now]
.l);
build
(mid+
1,r,tr[now]
.r);
}void
modify
(int l,
int r,
int per,
int&now,
int pos,
int w)
tr[now]
.l=tr[per]
.l; tr[now]
.r=tr[per]
.r;int mid=l+r>>1;
if(mid>=pos)
else
}int
query
(int l,
int r,
int ver,
int pos)
int mid=l+r>>1;
if(mid>=pos)
else
}int
main()
build(1
,n,root[0]
);int ver,op,pos,w,id=0;
for(
int i=
1;i<=q;i++
)else
}}
強調:
結構體中的l,r代表的是左右孩子節點,建樹過程中了l,r 代表的就是左右孩子節點,root[i],代表的是每乙個版本的根節點,通過根節點,可以找到這個版本的所有點,我們把當前版本和上一版本連起來即可理解後打的**:
#include
.h>
using namespace std;
//可持久化陣列
const
int maxn=
1e6+5;
struct node
tr[maxn*40]
;int root[maxn]
;//根節點
int a[maxn]
;int cnt;
void
build
(int l,
int r,
int&now)
//建一顆初始版本的樹
int m=l+r>>1;
build
(l,m,tr[now]
.l);
build
(m+1
,r,tr[now]
.r);
}void
modify
(int l,
int r,
int ver,
int&now,
int pos,
int w)
//修改一顆樹
int m=l+r>>1;
if(m>=pos)
else
}int
query
(int l,
int r,
int ver,
int pos)
int m=l+r>>1;
if(m>=pos)
else
}int
main()
build(1
,n,root[0]
);int id=0;
while
(q--
)else
}}
洛谷P3919 可持久化陣列
題目大意 需要維護乙個長度為 n 的陣列,支援在歷史版本上單點修改和單點查詢。題解 顯然,如果直接暴力維護的話會 mle。因此,採用線段樹進行維護,使得空間複雜度由 o mn 降至 o mlogn 不過相應的時間複雜度由 o 1 上公升至 o logn 如下 include using namesp...
洛谷P3919 模板 可持久化陣列
題目大意 有兩個操作,1 在第x次操作後的版本上修改乙個值,2 查詢在第x次操作後的版本上的乙個節點的值 即 你需要維護這樣的乙個長度為n的陣列,支援如下幾種操作 1.在某個歷史版本上修改某乙個位置上的值 2.訪問某個歷史版本上的某一位置的值 此外,每進行一次操作 對於操作2,即為生成乙個完全一樣的...
洛谷P3919 模板 可持久化陣列 主席樹
題目連線 如題,你需要維護這樣的乙個長度為n n的陣列,支援如下幾種操作 在某個歷史版本上修改某乙個位置上的值 訪問某個歷史版本上的某一位置的值 此外,每進行一次操作 對於操作2,即為生成乙個完全一樣的版本,不作任何改動 就會生成乙個新的版本。版本編號即為當前操作的編號 從1開始編號,版本0表示初始...