|
1 | 1 | #pragma once |
2 | 2 | #include <functional> |
3 | | -#include <iterator> |
4 | 3 | #include <vector> |
5 | 4 | #include "../utility/Exception.h" |
6 | 5 | #include "../common.h" |
7 | | -#include "../utility/Util.h" |
8 | 6 | namespace colinli { |
9 | 7 | namespace algon { |
10 | 8 |
|
11 | | - using std::vector; |
| 9 | +using std::vector; |
12 | 10 |
|
13 | | - template<typename TValue, typename TKey> |
14 | | - class SegmentTree |
15 | | - { |
16 | | - public: |
17 | | - typedef std::function<TValue(TKey)> Transformer; |
18 | | - typedef std::function<TValue(TValue, TValue)> Reducer; |
19 | | - SegmentTree(vector<TKey>& collection, Reducer reducer, Transformer trans) { |
20 | | - vector_ = collection; |
21 | | - reducer_ = reducer; |
22 | | - trans_ = trans; |
23 | | - root_ = build_tree(0, collection.size(), reducer, trans); |
24 | | - } |
25 | | - SegmentTree(vector<TKey>&& collection, Reducer reducer, Transformer trans) { |
26 | | - vector_ = collection; |
27 | | - reducer_ = reducer; |
28 | | - trans_ = trans; |
29 | | - root_ = build_tree(0, collection.size(), reducer, trans); |
30 | | - } |
| 11 | +#define LCHILD(i) (((i)<<1)+1) |
| 12 | +#define RCHILD(i) (((i)<<1)+2) |
31 | 13 |
|
32 | | - struct Node |
33 | | - { |
34 | | - Node* left; |
35 | | - Node* right; |
36 | | - TValue value; |
37 | | - explicit Node(TValue v) :value(v), left(nullptr), right(nullptr){} |
38 | | - explicit Node() :left(nullptr), right(nullptr), value(TValue()){} |
39 | | - }; |
40 | | - private: |
41 | | - Node* root_; |
42 | | - vector<TKey> vector_; |
43 | | - Transformer trans_; |
44 | | - Reducer reducer_; |
| 14 | +template <typename TValue, typename TKey> |
| 15 | +class SegmentTree |
| 16 | +{ |
| 17 | +public: |
| 18 | + typedef std::function<TValue(TKey)> Transformer; |
| 19 | + typedef std::function<TValue(TValue, TValue)> Reducer; |
45 | 20 |
|
46 | | - Node* build_tree(size_t begin,size_t end) { |
47 | | - if (begin == end) { |
48 | | - return NULL; |
49 | | - } |
50 | | - auto mid = begin + (end - begin) / 2; |
51 | | - Node* node = new Node(trans_(vector_.at(mid))); |
52 | | - node->left = build_tree(begin, mid); |
53 | | - node->right = build_tree( std::next(mid), end); |
54 | | - if (node->left && node->right) { |
55 | | - node->value = reducer_(node->left->value, node->right->value); |
56 | | - } |
57 | | - return node; |
58 | | - } |
| 21 | + SegmentTree(vector<TKey>& collection, Reducer reducer, Transformer trans, TValue initVal): |
| 22 | + vector_(collection), |
| 23 | + N(collection.size()), |
| 24 | + trans_(trans), |
| 25 | + reducer_(reducer), |
| 26 | + initVal_(initVal) { |
| 27 | + node_values_ = new TValue[(N << 2) + 1]; |
| 28 | + build_tree(0, 0, N-1); |
| 29 | + } |
| 30 | + |
| 31 | + void Update(size_t pos, TKey newkey) { |
| 32 | + update(0, 0, N - 1, pos, newkey); |
| 33 | + } |
| 34 | + |
| 35 | + TValue Query(size_t begin, size_t end) { |
| 36 | + return query(0, 0, N - 1, begin, end); |
| 37 | + } |
| 38 | + |
| 39 | + virtual ~SegmentTree() { |
| 40 | + delete[] node_values_; |
| 41 | + } |
| 42 | + |
| 43 | +private: |
| 44 | + vector<TKey> vector_; |
| 45 | + size_t N; |
| 46 | + Transformer trans_; |
| 47 | + Reducer reducer_; |
| 48 | + TValue initVal_; |
| 49 | + TValue* node_values_; |
59 | 50 |
|
60 | | - void update(Node* node ,size_t begin, size_t end, size_t pos, TKey newkey) { |
61 | | - if (begin == end || node == NULL) { |
62 | | - return; |
63 | | - } |
64 | | - if (++begin == end) { |
65 | | - node->value = trans_(newkey); |
66 | | - } |
67 | | - else { |
68 | | - auto mid = begin + (begin - end) / 2; |
69 | | - if ( pos <= mid ) { |
70 | | - update(node->left, begin, mid, pos, newkey); |
71 | | - update(node->right, mid+1 , end, pos, newkey); |
72 | | - CHECK_THROW(node->left && node->right, NullArgumentError); |
73 | | - node->value = reducer_(node->left->value, node->right->value); |
74 | | - } |
75 | | - } |
| 51 | + // build substree from x[begin...end] (inclusive range) |
| 52 | + void build_tree(size_t node_idx, size_t begin, size_t end) { |
| 53 | + //leaf node |
| 54 | + if (begin == end) { |
| 55 | + node_values_[node_idx] = trans_(vector_.at(begin)); |
| 56 | + return; |
76 | 57 | } |
77 | | - }; |
| 58 | + auto mid = begin + (end - begin) / 2; |
| 59 | + build_tree(LCHILD(node_idx), begin, mid); |
| 60 | + build_tree(RCHILD(node_idx), mid + 1, end); |
| 61 | + node_values_[node_idx] = reducer_(node_values_[LCHILD(node_idx)], node_values_[RCHILD(node_idx)]); |
| 62 | + } |
78 | 63 |
|
| 64 | + void update(size_t node_idx, size_t begin, size_t end, size_t pos, TKey newkey) { |
| 65 | + if (begin == end) { |
| 66 | + node_values_[node_idx] = trans_(newkey); |
| 67 | + return; |
| 68 | + } |
| 69 | + auto mid = begin + (end - begin) / 2; |
| 70 | + if (pos <= mid) { |
| 71 | + update(LCHILD(node_idx), begin, mid, pos, newkey); |
| 72 | + } |
| 73 | + else { |
| 74 | + update(RCHILD(node_idx), mid + 1, end, pos, newkey); |
| 75 | + } |
| 76 | + node_values_[node_idx] = reducer_(node_values_[LCHILD(node_idx)], node_values_[RCHILD(node_idx)]); |
| 77 | + } |
79 | 78 |
|
| 79 | + TValue query(size_t node_idx, size_t node_begin, size_t node_end, size_t q_begin, size_t q_end) { |
| 80 | + if (node_begin >= q_begin && node_end <= q_end) { |
| 81 | + return node_values_[node_idx]; |
| 82 | + } |
| 83 | + auto mid = node_begin + (node_end - node_begin) / 2; |
| 84 | + TValue result = initVal_; |
| 85 | + if (mid > q_begin && node_begin <= q_end) { |
| 86 | + result = reducer_(result, query(LCHILD(node_idx), node_begin, mid, q_begin, q_end)); |
| 87 | + } |
| 88 | + if (node_end >= q_begin && mid + 1 <= q_end) { |
| 89 | + result = reducer_(result, query(RCHILD(node_idx), mid + 1, node_end, q_begin, q_end)); |
| 90 | + } |
| 91 | + return result; |
| 92 | + } |
| 93 | +}; |
80 | 94 |
|
81 | 95 | }// end of algon ns |
82 | 96 | }// end of colinli ns |
|
0 commit comments