107 IntegerType energy_min, IntegerType energy_max) {
108 DCHECK_LE(0, energy_min);
109 DCHECK_LE(energy_min, energy_max);
110 const int node = GetLeafFromEvent(event);
111 tree_[node] = {.envelope = initial_envelope + energy_min,
112 .envelope_opt = initial_envelope + energy_max,
113 .sum_of_energy_min = energy_min,
114 .max_of_energy_delta = energy_max - energy_min};
124 IntegerType energy_max) {
125 DCHECK_LE(0, energy_max);
126 const int node = GetLeafFromEvent(event);
127 tree_[node] = {.envelope = std::numeric_limits<IntegerType>::min(),
128 .envelope_opt = initial_envelope_opt + energy_max,
129 .sum_of_energy_min = IntegerType{0},
130 .max_of_energy_delta = energy_max};
136 const int node = GetLeafFromEvent(event);
137 tree_[node] = {.envelope = std::numeric_limits<IntegerType>::min(),
138 .envelope_opt = std::numeric_limits<IntegerType>::min(),
139 .sum_of_energy_min = IntegerType{0},
140 .max_of_energy_delta = IntegerType{0}};
159 DCHECK_LT(target_envelope, tree_[1].envelope);
161 return GetEventFromLeaf(
162 GetMaxLeafWithEnvelopeGreaterThan(1, target_envelope, &unused));
187 IntegerType target_envelope,
int* critical_event,
int* optional_event,
188 IntegerType* available_energy)
const {
191 GetLeavesWithOptionalEnvelopeGreaterThan(target_envelope, &critical_leaf,
192 &optional_leaf, available_energy);
193 *critical_event = GetEventFromLeaf(critical_leaf);
194 *optional_event = GetEventFromLeaf(optional_leaf);
199 return tree_[GetLeafFromEvent(event)].sum_of_energy_min;
204 IntegerType envelope;
205 IntegerType envelope_opt;
206 IntegerType sum_of_energy_min;
207 IntegerType max_of_energy_delta;
210 TreeNode ComposeTreeNodes(
const TreeNode& left,
const TreeNode& right) {
213 std::max(right.envelope, left.envelope + right.sum_of_energy_min),
215 std::max(right.envelope_opt,
216 right.sum_of_energy_min +
217 std::max(left.envelope_opt,
218 left.envelope + right.max_of_energy_delta)),
219 .sum_of_energy_min = left.sum_of_energy_min + right.sum_of_energy_min,
220 .max_of_energy_delta =
221 std::max(right.max_of_energy_delta, left.max_of_energy_delta)};
224 int GetLeafFromEvent(
int event)
const {
226 DCHECK_LT(event, num_events_);
230 const int r = power_of_two_ + event;
231 return r < 2 * num_leaves_ ? r : r - num_leaves_;
234 int GetEventFromLeaf(
int leaf)
const {
235 DCHECK_GE(leaf, num_leaves_);
236 DCHECK_LT(leaf, 2 * num_leaves_);
237 const int r = leaf - power_of_two_;
238 return r >= 0 ? r : r + num_leaves_;
242 void RefreshNode(
int node);
248 int GetMaxLeafWithEnvelopeGreaterThan(
int node, IntegerType target_envelope,
249 IntegerType* extra)
const;
252 int GetLeafWithMaxEnergyDelta(
int node)
const;
256 void GetLeavesWithOptionalEnvelopeGreaterThan(
257 IntegerType target_envelope,
int* critical_leaf,
int* optional_leaf,
258 IntegerType* available_energy)
const;
266 std::vector<TreeNode> tree_;
269template <
typename IntegerType>
274 num_events_ = num_events;
275 num_leaves_ = std::max(2, num_events + (num_events & 1));
277 const int num_nodes = 2 * num_leaves_;
278 tree_.assign(num_nodes,
279 TreeNode{.envelope = std::numeric_limits<IntegerType>::min(),
280 .envelope_opt = std::numeric_limits<IntegerType>::min(),
281 .sum_of_energy_min = IntegerType{0},
282 .max_of_energy_delta = IntegerType{0}});
288 for (power_of_two_ = 2; power_of_two_ < num_leaves_; power_of_two_ <<= 1) {
292template <
typename IntegerType>
294 const int leaf = GetLeafFromEvent(event);
295 IntegerType envelope = tree_[leaf].envelope;
296 for (
int node = leaf; node > 1; node >>= 1) {
297 const int right = node | 1;
298 if (node != right) envelope += tree_[right].sum_of_energy_min;
303template <
typename IntegerType>
304void ThetaLambdaTree<IntegerType>::RefreshNode(
int node) {
305 TreeNode* tree = tree_.data();
307 const int right = node | 1;
308 const int left = right ^ 1;
310 tree[node] = ComposeTreeNodes(tree[left], tree[right]);
314template <
typename IntegerType>
315int ThetaLambdaTree<IntegerType>::GetMaxLeafWithEnvelopeGreaterThan(
316 int node, IntegerType target_envelope, IntegerType* extra)
const {
317 DCHECK_LT(target_envelope, tree_[node].envelope);
318 while (node < num_leaves_) {
319 const int left = node << 1;
320 const int right = left | 1;
321 DCHECK_LT(right, tree_.size());
323 if (target_envelope < tree_[right].envelope) {
326 target_envelope -= tree_[right].sum_of_energy_min;
330 *extra = tree_[node].envelope - target_envelope;
334template <
typename IntegerType>
335int ThetaLambdaTree<IntegerType>::GetLeafWithMaxEnergyDelta(
int node)
const {
336 const IntegerType delta_node = tree_[node].max_of_energy_delta;
337 while (node < num_leaves_) {
338 const int left = node << 1;
339 const int right = left | 1;
340 DCHECK_LT(right, tree_.size());
341 if (tree_[right].max_of_energy_delta == delta_node) {
344 DCHECK_EQ(tree_[left].max_of_energy_delta, delta_node);
351template <
typename IntegerType>
352void ThetaLambdaTree<IntegerType>::GetLeavesWithOptionalEnvelopeGreaterThan(
353 IntegerType target_envelope,
int* critical_leaf,
int* optional_leaf,
354 IntegerType* available_energy)
const {
355 DCHECK_LT(target_envelope, tree_[1].envelope_opt);
357 while (node < num_leaves_) {
358 const int left = node << 1;
359 const int right = left | 1;
360 DCHECK_LT(right, tree_.size());
362 if (target_envelope < tree_[right].envelope_opt) {
365 const IntegerType opt_energy_right =
366 tree_[right].sum_of_energy_min + tree_[right].max_of_energy_delta;
367 if (target_envelope < tree_[left].envelope + opt_energy_right) {
368 *optional_leaf = GetLeafWithMaxEnergyDelta(right);
370 *critical_leaf = GetMaxLeafWithEnvelopeGreaterThan(
371 left, target_envelope - opt_energy_right, &extra);
372 *available_energy = tree_[*optional_leaf].sum_of_energy_min +
373 tree_[*optional_leaf].max_of_energy_delta - extra;
376 target_envelope -= tree_[right].sum_of_energy_min;
381 *critical_leaf = node;
382 *optional_leaf = node;
383 *available_energy = target_envelope - (tree_[node].envelope_opt -
384 tree_[node].sum_of_energy_min -
385 tree_[node].max_of_energy_delta);