題目連線:
如題,你需要維護這樣的乙個長度為n
n的陣列,支援如下幾種操作
在某個歷史版本上修改某乙個位置上的值
訪問某個歷史版本上的某一位置的值
此外,每進行一次操作(對於操作2,即為生成乙個完全一樣的版本,不作任何改動),就會生成乙個新的版本。版本編號即為當前操作的編號(從1開始編號,版本0表示初始狀態陣列)
主席樹模板題。
主席樹的題目大多是單點修改的。當我們需要支援訪問歷史版本時,最簡單的方法是新建一棵線段樹。
但是這樣的記憶體會**的。
我們發現,由於只要單點修改,所以我們需要修改的就只有這個節點以及他的祖宗,其他點就是根本不用修改的,所以如果我們可以只修改需要修改的點,其他點直接連向原本線段樹的點,就可以大大壓縮空間
。雖然這樣空間複雜度還是會很高
假設我們有一棵這樣的線段樹
其中l,rl
,r分別表示左兒子和右兒子。
此時如果我們需要修改點10,就可以得到下面這樣一棵主席樹
注意節點13,14的左兒子和右兒子的位置還是不變的。
此時如果我們需要訪問歷史版本0,就從根節點1為的主席樹找,如果要訪問歷史版本1,就從根及誒單為12的主席樹找。
這樣的時間複雜度是o(m
logn
)o(m
logn
),空間複雜度是o(n
+mlo
gn)o
(n+m
logn
)。為了節省空間,主席樹的區間表示不再在結構體中記錄,而是使用遞迴引數來傳遞。
#include
using
namespace std;
const
int n=
1e6+10;
const
int m=n+
20*n;
int n,m,a[n]
,root[n]
,tot,s,k,val,x;
struct tree
tree[m*2]
;int
build
(int l,
int r)
return p;
}int
change
(int now,
int l,
int r,
int k,
int val)
//修改
return p;
}int
ask(
int now,
int l,
int r,
int k)
//查詢
return p;
}int
main()
else
}return0;
}
洛谷P3919 模板 可持久化陣列
題目大意 有兩個操作,1 在第x次操作後的版本上修改乙個值,2 查詢在第x次操作後的版本上的乙個節點的值 即 你需要維護這樣的乙個長度為n的陣列,支援如下幾種操作 1.在某個歷史版本上修改某乙個位置上的值 2.訪問某個歷史版本上的某一位置的值 此外,每進行一次操作 對於操作2,即為生成乙個完全一樣的...
洛谷P3919 可持久化陣列
題目大意 需要維護乙個長度為 n 的陣列,支援在歷史版本上單點修改和單點查詢。題解 顯然,如果直接暴力維護的話會 mle。因此,採用線段樹進行維護,使得空間複雜度由 o mn 降至 o mlogn 不過相應的時間複雜度由 o 1 上公升至 o logn 如下 include using namesp...
洛谷P3919可持久化線段樹
有了可持久化陣列,便可以實現很多衍生的可持久化功能 例如 可持久化並查集 如題,你需要維護這樣的乙個長度為 n 的陣列,支援如下幾種操作 在某個歷史版本上修改某乙個位置上的值 訪問某個歷史版本上的某一位置的值 此外,每進行一次操作 對於操作2,即為生成乙個完全一樣的版本,不作任何改動 就會生成乙個新...