[Luogu 3919]【模板】可持久化數組(可持久化線段樹/平衡樹)
Description
如題,你需要維護這樣的一個長度為 N 的數組,支持如下幾種操作
-
在某個歷史版本上修改某一個位置上的值
- 訪問某個歷史版本上的某一位置的值
此外,每進行一次操作(對於操作2,即為生成一個完全一樣的版本,不作任何改動),就會生成一個新的版本。版本編號即為當前操作的編號(從1開始編號,版本0表示初始狀態數組)
Input
輸入的第一行包含兩個正整數 N, M, 分別表示數組的長度和操作的個數。
第二行包含N個整數,依次為初始狀態下數組各位的值(依次為 a_i,1≤i≤N)。
接下來M行每行包含3或4個整數,代表兩種操作之一(ii為基於的歷史版本號):
-
對於操作1,格式為v?i?? 1 loc?i?? value?i??,即為在版本v_iv?i??的基礎上,將 a?loc?i???? 修改為 value?i??
- 對於操作2,格式為v?i?? 2 loc?i?? ,即訪問版本 v?i?? 中的 a?loc?i???? 的值
Output
輸出包含若幹行,依次為每個操作2的結果。
Sample Input
5 10
59 46 14 87 41
0 2 1
0 1 1 14
0 1 1 57
0 1 1 88
4 2 4
0 2 5
0 2 4
4 2 1
2 2 2
1 1 5 91
Sample Output
59
87
41
87
88
46
HINT
數據規模:
對於30%的數據:1≤N,M≤10?3??
對於50%的數據:1≤N,M≤10?4??
對於70%的數據:1≤N,M≤10?5??
對於100%的數據:1≤N,M≤10?6??,1≤loc?i??≤N,0≤v?i??<i,−10?9??≤a?i??,value?i??≤10?9??
經測試,正常常數的可持久化數組可以通過,請各位放心
數據略微兇殘,請註意常數不要過大
另,此題I/O量較大,如果實在TLE請註意I/O優化
樣例說明:
一共11個版本,編號從0-10,依次為:
-
0 : 59 46 14 87 41
-
1 : 59 46 14 87 41
-
2 : 14 46 14 87 41
-
3 : 57 46 14 87 41
-
4 : 88 46 14 87 41
-
5 : 88 46 14 87 41
-
6 : 59 46 14 87 41
-
7 : 59 46 14 87 41
-
8 : 88 46 14 87 41
-
9 : 14 46 14 87 41
- 10 : 59 46 14 87 91
題解
$rt$,當模板存著...
1 //It is made by Awson on 2017.10.3 2 #include <set> 3 #include <map> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <cstdio> 10 #include <string> 11 #include <cstring> 12 #include <cstdlib> 13 #include <iostream> 14 #include <algorithm> 15 #define LL long long 16 #define Max(a, b) ((a) > (b) ? (a) : (b)) 17 #define Min(a, b) ((a) < (b) ? (a) : (b)) 18 #define sqr(x) ((x)*(x)) 19 #define insert INSERT 20 using namespace std; 21 const int N = 1e6; 22 void read(int &x) { 23 char ch; bool flag = 0; 24 for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == ‘-‘)) || 1); ch = getchar()); 25 for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar()); 26 x *= 1-2*flag; 27 } 28 29 struct node { 30 int key; 31 node *child[2]; 32 }sgm[N*20+5], *pos = sgm; 33 node* root[N+5]; 34 int n, m, a[N+5]; 35 int opt, v, loc, val; 36 37 void build(node *o, int l, int r) { 38 if (l == r) { 39 o->key = a[l]; 40 return; 41 } 42 int mid = (l+r)>>1; 43 o->child[0] = ++pos; build(o->child[0], l, mid); 44 o->child[1] = ++pos; build(o->child[1], mid+1, r); 45 } 46 void insert(node* &o, int l, int r, int loc, int val) { 47 node* tmp = o; 48 o = ++pos; 49 if (l == r) { 50 o->key = val; 51 return; 52 }else { 53 o->child[0] = tmp->child[0]; 54 o->child[1] = tmp->child[1]; 55 } 56 int mid = (l+r)>>1; 57 if (loc <= mid) insert(o->child[0], l, mid, loc, val); 58 else insert(o->child[1], mid+1, r, loc, val); 59 } 60 int query(node *o, int l, int r, int loc) { 61 if (l == r) return o->key; 62 int mid = (l+r)>>1; 63 if (loc <= mid) return query(o->child[0], l, mid, loc); 64 else return query(o->child[1], mid+1, r, loc); 65 } 66 void work() { 67 read(n), read(m); 68 for (int i = 1; i <= n; i++) read(a[i]); 69 root[0] = pos; 70 build(root[0], 1, n); 71 for (int i = 1; i <= m; i++) { 72 read(v), read(opt); 73 if (opt == 1) { 74 read(loc), read(val); 75 root[i] = root[v]; 76 insert(root[i], 1, n, loc, val); 77 } 78 else { 79 read(loc); 80 root[i] = root[v]; 81 printf("%d\n", query(root[i], 1, n, loc)); 82 } 83 } 84 } 85 int main() { 86 work(); 87 return 0; 88 }
[Luogu 3919]【模板】可持久化數組(可持久化線段樹/平衡樹)