-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPersistent segment tree implementation with array.cpp
More file actions
147 lines (108 loc) · 3.32 KB
/
Persistent segment tree implementation with array.cpp
File metadata and controls
147 lines (108 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Persistent segment tree implementation with array (not pointer).
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 10 + 3;
struct Node {
int sum; // To store sum of the elements in node.
int leftId, rightId; // ID to left and right children.
Node(int s = 0, int l = -1, int r = -1) {
sum = s, leftId = l, rightId = r;
}
};
int arr[MAXN]; // Input array.
int treeSize = 0;
vector<int> roots; // Root IDs for all versions.
vector<Node> tree;
void build(int nodeId, int s, int t) // To construct version-0.
{
if(s == t) {
tree[nodeId].sum = arr[s];
return;
}
int left, right, mid = (s + t) >> 1;
tree.push_back(Node()); tree.push_back(Node());
tree[nodeId].leftId = left = treeSize++;
tree[nodeId].rightId = right = treeSize++;
build(left, s, mid);
build(right, mid+1, t);
tree[nodeId].sum = tree[left].sum + tree[right].sum;
}
void upgrade(int prevNodeId, int currNodeId, int s, int t, int idx, int val) // Upgrades to new version.
{
if(s == t) { // s == t == idx
tree[currNodeId].sum = val;
return;
}
int left, right, mid = (s + t) >> 1;
tree.push_back(Node());
if(idx <= mid) {
tree[currNodeId].rightId = right = tree[prevNodeId].rightId; // Link to right child of previous version.
tree[currNodeId].leftId = left = treeSize++;
upgrade(tree[prevNodeId].leftId, left, s, mid, idx, val);
}
else {
tree[currNodeId].leftId = left = tree[prevNodeId].leftId; // Link to left child of previous version.
tree[currNodeId].rightId = right = treeSize++;
upgrade(tree[prevNodeId].rightId, right, mid+1, t, idx, val);
}
tree[currNodeId].sum = tree[left].sum + tree[right].sum;
}
int query(int nodeId, int s, int t, int rs, int rt)
{
if(t < rs || rt < s) return 0;
if(rs <= s && t <= rt) return tree[nodeId].sum;
int mid = (s + t) >> 1;
int q1 = query(tree[nodeId].leftId, s, mid, rs, rt);
int q2 = query(tree[nodeId].rightId, mid+1, t, rs, rt);
return q1 + q2;
}
int main()
{
//freopen("in.txt", "r", stdin);
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d", arr+i);
tree.push_back(Node());
roots.push_back(0);
build(treeSize++, 1, n);
int updt, idx, val;
scanf("%d", &updt);
while(updt--) {
scanf("%d %d", &idx, &val);
tree.push_back(Node());
roots.push_back(treeSize);
upgrade(roots[roots.size()-2], treeSize++, 1, n, idx, val);
}
int qry, version, l, r;
scanf("%d", &qry);
while(qry--) {
scanf("%d %d %d", &version, &l, &r);
int res = query(roots[version], 1, n, l, r);
printf("In version %d, query(%2d, %2d) : %d\n", version, l, r, res);
}
return 0;
}
/*
Problem:
Given an array and different point update operations.
Considering each point operation to create a new version of the array, we need to answer the queries of type
v l r : output the sum of elements in range l to r just after the v-th update.
Input:
10
1 2 3 4 5 6 7 8 9 10
3
2 4
5 25
10 123
4
0 1 10
1 1 2
2 4 8
3 1 10
Output:
In version 0, query( 1, 10) : 55
In version 1, query( 1, 2) : 5
In version 2, query( 4, 8) : 50
In version 3, query( 1, 10) : 190
*/