SegmentTree.cpp 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // segment tree for minimum and sum
  2. // root is in tree[1], children in tree[2i] and tree[2i+1]
  3. // all ranges in build/updates/queries are 0-based
  4. const int INFI=1000000000;
  5. struct Node {
  6. int min, sum, up, size; // size of subtree
  7. void update(int x) {
  8. min += x;
  9. sum += x*size;
  10. up += x;
  11. }
  12. Node() {
  13. min = INFI;
  14. up = sum = size = 0;
  15. }
  16. };
  17. Node *tree;
  18. int N;
  19. void compute(int v) { // update tree[v] from its children, v < N
  20. tree[v].min = min(tree[2*v].min, tree[2*v+1].min);
  21. tree[v].sum = tree[2*v].sum + tree[2*v+1].sum;
  22. }
  23. // read values[0..size-1]
  24. void build(int size, int values[]) {
  25. N = size > 1 ? 1 << ((int)log2(size-1)+1) : 1;
  26. tree = new Node[2*N];
  27. for(int i = 0; i < size; i++) { // leaves
  28. tree[N+i].min = tree[N+i].sum = values[i];
  29. tree[N+i].size = 1;
  30. }
  31. for(int i = N-1; i > 0; i--) { // interns
  32. compute(i);
  33. tree[i].size = tree[2*i].size + tree[2*i+1].size;
  34. }
  35. }
  36. void push(int v) {
  37. if(2*v < 2*N) // left subtree
  38. tree[2*v].update(tree[v].up);
  39. if(2*v+1 < 2*N) // right subtree
  40. tree[2*v+1].update(tree[v].up);
  41. tree[v].up = 0;
  42. }
  43. // v: current vertex with corressponding range [left, right)
  44. // find mimimum and sum of the range [l, r)
  45. pair<int, int> query_aux(int v, int left, int right, int l, int r) {
  46. push(v);
  47. if(right <= l || r <= left) // outside
  48. return {INFI, 0};
  49. if(l <= left && right <= r) // inside
  50. return {tree[v].min, tree[v].sum};
  51. int m = (left+right)/2;
  52. int lm, rm, ls, rs;
  53. tie(lm, ls) = query_aux(2*v, left, m, l, r); // left subtree
  54. tie(rm, rs) = query_aux(2*v+1, m, right, l, r); // right
  55. return {min(lm, rm), ls+rs};
  56. }
  57. pair<int, int> query(int l, int r) {
  58. return query_aux(1, 0, N, l, r);
  59. }
  60. // update element at index i with value x
  61. void update(int i, int x) {
  62. i+=N;
  63. // push path from 1 to i
  64. int po = N;
  65. for(int v = 1; v < i;) {
  66. push(v);
  67. v*=2;
  68. if(i & po)
  69. v++; // i on right
  70. po /= 2;
  71. }
  72. tree[i].min = tree[i].sum = x; // update el
  73. for(i /= 2; i > 0; i /= 2) // update all segments containing i
  74. compute(i);
  75. }
  76. // v: the current vertex with corressponding range in [left, right)
  77. // add value x for element in range [l, r)
  78. void update_range_aux(int v, int left, int right, int l, int r, int x) {
  79. push(v);
  80. if(right <= l || r <= left)
  81. return;
  82. if(l <= left && right <= r) {
  83. tree[v].update(x);
  84. return;
  85. }
  86. int m = (left+right)/2;
  87. update_range_aux(2*v, left, m, l, r, x);
  88. update_range_aux(2*v+1, m, right, l, r, x);
  89. compute(v);
  90. }
  91. // update [l,r)
  92. void update_range(int l, int r, int x) {
  93. update_range_aux(1, 0, N, l, r, x);
  94. }