aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/dsa/BinaryIndexTree.h
blob: 1d2d9e8cb952f2daf2cbbf0bf58bc47d016ac0cc (plain) (blame)
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
#ifndef   dsa_BinaryIndexTree_H__
#define   dsa_BinaryIndexTree_H__

#include <cstdlib>

#include <vector>
#include <algorithm>

namespace meow {

template<class Value>
/*!
 * @brief 極度簡化的 \c SegmentTree 已無區間更新的操作
 *
 * 一般來說只能用在維護區間總和, 維護區間最大值只有在特殊情況才可以, 即
 * \b 針對每個元素, \b 每次update() \b 的值一定會大於等於原本的值 .
 * 若要用區間最大值 , 則 \a Value 的 \c operator+  要寫成 \c std::max(...)
 *
 * @author cat_leopard
 */
class BinaryIndexTree {
private:
  std::vector<Value> array_;
public:
  /*!
   * @brief constructor
   */
  BinaryIndexTree() {
  }

  /*!
   * @brief constructor
   *
   * @param [in] size 要維護的區間大小 \b [0,size)
   * @param [in] value 預設值
   */
  BinaryIndexTree(size_t size, Value const& value):
  array_(size, value) {
  }

  /*!
   * @brief constructor
   *
   * 將另一個 \c BinaryIndexTree 原封不動的複製過來
   * @param [in] tree2 另外一個 \c BinaryIndexTree
   */
  BinaryIndexTree(BinaryIndexTree const& tree2):
  array_(tree2.array_) {
  }

  /*!
   * @brief 將資料洗掉, 重設
   *
   * 時間複雜度\b O(N)
   *
   * @param [in] size 要維護的區間大小 \b [0,size)
   * @param [in] init 預設值
   * @return 無
   */
  void reset(size_t size, Value const& init) {
    array_.clear();
    array_.resize(size, init);
  }

  /*!
   * @brief 將array中第 \a index (從零算起)個element多加上指定的值
   *
   * 時間複雜度\b O(logN)
   *
   * @param [in] index 指定的index
   * @param [in] value 指定的值
   * @return 無
   */
  void update(size_t index, Value const& value) {
    index++;
    for ( ; index <= array_.size(); index += (index & -index)) {
      array_[index - 1] = array_[index - 1] + value;
    }
  }


  /*!
   * @brief 詢問 \a 0~index 的區間值
   *
   * 時間複雜度\b O(logN)
   *
   * @param [in] index 指定的index
   * @return 區間值
   */
  Value query(ssize_t index) const {
    index = std::min(index + 1, (ssize_t)array_.size());
    Value ret(0);
    for ( ; 0 < index; index -= (index & -index)) {
      ret = ret + array_[index - 1];
    }
    return ret;
  }
};

} // meow

#endif // dsa_BinaryIndexTree_H__