-
Notifications
You must be signed in to change notification settings - Fork 0
/
tree.cpp
186 lines (154 loc) · 2.97 KB
/
tree.cpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <iostream>
#include <algorithm>
#include <ext/pb_ds/assoc_container.hpp>
typedef unsigned long long ull;
template <typename num_type>
struct PlusMaxNode
{
num_type result;
num_type base;
void update(const PlusMaxNode & left, const PlusMaxNode & right)
{
result = base + left.result + right.result;
}
void insert(num_type value)
{
base += value;
result += value;
}
int query(num_type result)
{
return std::max(this->result,result);
}
};
template<
typename node_type,
ull K,
typename range_index = ull>
struct Tree
{
typedef typename __gnu_pbds::cc_hash_table<range_index,node_type> table;
table tree;
static const range_index ROOT = 1;
static const range_index N = 1LL<<K;
struct Index
{
table & tree;
range_index index;
Index& operator=(const Index& a)
{
tree = a.tree;
return *this;
}
Index(table & t,range_index position) : tree(t), index(position+N)
{}
Index(Index * a,range_index index) : tree(a->tree), index(index)
{}
operator bool() const
{
return index;
}
operator node_type&() const
{
return tree[index];
}
Index brother()
{
if(isLeft())
return Index(this, index + 1);
return Index(this,index-1);
}
Index father()
{
return Index(this, index / 2);
}
Index left()
{
return Index(this, index * 2);
}
Index right()
{
return Index(this, index*2 + 1);
}
bool isLeft()
{
return (index%2) == 0;
}
bool isRight()
{
return ! isRight();
}
bool operator!=(Index& b)
{
return index != b.index;
}
void show()
{
std::cout<<index<<std::endl;
}
void update()
{
tree[index].update(left(),right());
}
int query(int result)
{
return tree[index].query(result);
}
void insert(int value)
{
tree[index].query(value);
}
};
void show(range_index index = ROOT)
{
if(index > 2*N-1)
return;
show(index*2+1);
std::cout <<std::string((int)(floor(log2(index))),'\t')
<<"["<<index<<"]=( "
<<tree[index].result <<' '
<<tree[index].base<<" )"<<std::endl;
show(index*2);
}
void insert(range_index positionA, range_index positionB ,int value=1)
{
Index a(tree,positionA);
Index b(tree,positionB);
a.insert(value);
if(a != b)
b.insert(value);
while(a.father() != b.father())
{
if(a.isLeft())
a.brother().insert(value);
if(b.isRight())
b.brother().insert(value);
a = a.father();
b = b.father();
a.update();
b.update();
}
while(a = a.father())
a.update();
}
int query(range_index positionA, range_index positionB)
{
Index a(tree,positionA);
Index b(tree,positionB);
int result = a.query(0);
if(a != b)
result = b.query(result);
while(a.father() != b.father())
{
if(a.isLeft())
result = a.query(result);
if(b.isRight())
result = b.query(result);
a = a.father();
b = b.father();
}
while(a = a.father())
result = a.query(result);
return result;
}
};