-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsegtree2d.cpp
More file actions
140 lines (120 loc) · 3.68 KB
/
Copy pathsegtree2d.cpp
File metadata and controls
140 lines (120 loc) · 3.68 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
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
// dynamic variant
#define MAXR (int)1e9
#define MAXC (int)1e9
// func must be associative
long long func(ll a, ll b) {
return a + b;
}
struct layer2_node {
int low;
int high;
layer2_node* lft;
layer2_node* rht;
ll value;
layer2_node(int low, int high)
: low(low), high(high), lft(NULL), rht(NULL), value(0LL) {
}
};
struct layer1_node {
layer1_node* lft;
layer1_node* rht;
layer2_node l2;
layer1_node() : lft(NULL), rht(NULL), l2(0, MAXC) {
}
};
static layer1_node root;
static void update2(layer2_node* node, int Q, long long K) {
int low = node->low;
int high = node->high;
int mid = (low + high) / 2;
if(low + 1 == high) {
/* For leaf nodes we just update the value directly. */
node->value = K;
return;
}
layer2_node*& tgt = Q < mid ? node->lft : node->rht;
if(tgt == NULL) {
/* If there is no node on this side of the tree create a new leaf node
* containing exactly our update point. */
tgt = new layer2_node(Q, Q + 1);
tgt->value = K;
} else if(tgt->low <= Q && Q < tgt->high) {
/* If the existing node contains our query point continue inserting there.
*/
update2(tgt, Q, K);
} else {
/* Otherwise traverse down the virtual tree until the side of our query node
* and the side of the existing node differ. Create this node and continue
* updating along it. */
do {
(Q < mid ? high : low) = mid;
mid = (low + high) / 2;
} while((Q < mid) == (tgt->low < mid));
layer2_node* nnode = new layer2_node(low, high);
(tgt->low < mid ? nnode->lft : nnode->rht) = tgt;
tgt = nnode;
update2(nnode, Q, K);
}
/* Internal nodes get updated as the gcd of its leaves. */
node->value = func(node->lft ? node->lft->value : 0,
node->rht ? node->rht->value : 0);
}
long long query2(layer2_node* nd, int A, int B) {
/* The same as the level 1 queries except the interval each node represents
* may skip some levels of the tree so we store them in the node itself. */
if(nd == NULL || B <= nd->low || nd->high <= A) {
return 0;
} else if(A <= nd->low && nd->high <= B) {
return nd->value;
}
return func(query2(nd->lft, A, B), query2(nd->rht, A, B));
}
static void update1(layer1_node* node, int low, int high,
int P, int Q, ll K) {
int mid = (low + high) / 2;
if(low + 1 == high) {
update2(&node->l2, Q, K);
} else {
layer1_node*& nnode = P < mid ? node->lft : node->rht;
(P < mid ? high : low) = mid;
if(nnode == NULL) {
nnode = new layer1_node();
}
update1(nnode, low, high, P, Q, K);
/* Compute what value to update with. */
K = func(node->lft ? query2(&node->lft->l2, Q, Q + 1) : 0,
node->rht ? query2(&node->rht->l2, Q, Q + 1) : 0);
update2(&node->l2, Q, K);
}
}
long long query1(layer1_node* nd, int low, int high,
int A1, int B1, int A2, int B2) {
/* Scan down the tree short-circuiting when we reach a node that contains
* our entire query interval and combining the result of the level2 queries.
*/
if(nd == NULL || B1 <= low || high <= A1) {
return 0;
} else if(A1 <= low && high <= B1) {
return query2(&nd->l2, A2, B2);
}
int mid = (low + high) / 2;
return func(query1(nd->lft, low, mid, A1, B1, A2, B2),
query1(nd->rht, mid, high, A1, B1, A2, B2));
}
void init(int R, int C) {
}
void update(int P, int Q, ll K) {
update1(&root, 0, MAXR, P, Q, K);
}
long long calculate(int P, int Q, int U, int V) {
return query1(&root, 0, MAXR, P, U + 1, Q, V + 1);
}
int main(){
update(0, 0, 2);
update(5, 5, 3);
cout << calculate(0, 0, 10, 10) << endl;
return 0;
}