SegmentTree.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // segment tree for minimum
  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 v; int up;
  7. void update(int x) {
  8. v += x;
  9. up += x;
  10. }
  11. Node() {
  12. v = INFI;
  13. up = 0;
  14. }
  15. };
  16. Node *tree;
  17. int N;
  18. // read values[0..size-1]
  19. void build(int size, int values[]) {
  20. N = 1 << ((int)log2(size-1)+1);
  21. tree = new Node[2*N];
  22. for(int i = 0; i < size; i++) // leaves
  23. tree[N+i].v = values[i];
  24. for(int i = N-1; i > 0; i--) // interns
  25. tree[i].v = min(tree[2*i].v, tree[2*i+1].v);
  26. }
  27. void push(int v) {
  28. if(2*v < 2*N) // left subtree
  29. tree[2*v].update(tree[v].up);
  30. if(2*v+1 < 2*N) // right subtree
  31. tree[2*v+1].update(tree[v].up);
  32. tree[v].up = 0;
  33. }
  34. // v: current vertex with corressponding range [left, right)
  35. // find mimimum in the rangeg [l, r)
  36. int query_aux(int v, int left, int right, int l, int r) {
  37. push(v);
  38. if(right <= l || r <= left) // outside
  39. return INFI;
  40. if(l <= left && right <= r) // inside
  41. return tree[v].v;
  42. int m = (left+right)/2;
  43. int left_min = query_aux(2*v, left, m, l, r); // left subtree
  44. int right_min = query_aux(2*v+1, m, right, l, r); // right
  45. return min(left_min, right_min);
  46. }
  47. int query(int l, int r) {
  48. return query_aux(1, 0, N, l, r);
  49. }
  50. // update element at index i with value x
  51. void update(int i, int x) {
  52. i+=N;
  53. // push path from 1 to i
  54. int po = N;
  55. for(int v = 1; v < i;) {
  56. push(v);
  57. if(i & po)
  58. v = 2*v + 1; // i on right
  59. else
  60. v = 2*v; // left
  61. po /= 2;
  62. }
  63. tree[i].v = x; // update el
  64. for(i /= 2; i > 0; i /= 2) // update all segments containing i
  65. tree[i].v = min(tree[2*i].v, tree[2*i+1].v);
  66. }
  67. // v: the current vertex with corressponding range in [left, right)
  68. // add value x for element in range [l, r)
  69. void update_range_aux(int v, int left, int right, int l, int r, int x) {
  70. push(v);
  71. if(right <= l || r <= left)
  72. return;
  73. if(l <= left && right <= r) {
  74. tree[v].update(x);
  75. return;
  76. }
  77. int m = (left+right)/2;
  78. update_range_aux(2*v, left, m, l, r, x);
  79. update_range_aux(2*v+1, m, right, l, r, x);
  80. tree[v].v = min(tree[2*v].v, tree[2*v+1].v);
  81. }
  82. // update [l,r)
  83. void update_range(int l, int r, int x) {
  84. update_range_aux(1, 0, N, l, r, x);
  85. }