CP-templates

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Misuki743/CP-templates

:heavy_check_mark: segtree/segmentTree.cpp

Verified with

Code

template<class M, M(*id)(), M(*op)(const M&, const M&)>
struct segmentTree {
  int size;
  vector<M> data;

  segmentTree(int _size) : size(_size), data(2 * size, id()) {}
  segmentTree(vector<M> init) : size(ssize(init)), data(2 * size, id()) {
    ranges::copy(init, data.begin() + size);
    for(int i = size - 1; i > 0; i--)
      data[i] = op(data[i << 1], data[i << 1 | 1]);
  }

  void set(int i, M x) {
    data[i += size] = x;
    while(i >>= 1)
      data[i] = op(data[i << 1], data[i << 1 | 1]);
  }

  M get(int i) { return data[i + size]; }

  M query(int l, int r) {
    M L = id(), R = id();
    for(l += size, r += size; l < r; l >>= 1, r >>= 1) {
      if (l & 1) L = op(L, data[l++]);
      if (r & 1) R = op(data[--r], R);
    }
    return op(L, R);
  }

  //return first j in [i, size) s.t. f(op([l, j])) is true,
  //assume f(id()) is false.
  int firstTrue(int i, function<bool(const M&)> f) {
    vector<int> idL, idR;
    for(int l = i + size, r = size << 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1) idL.emplace_back(l++);
      if (r & 1) idR.emplace_back(--r);
    }
    idL.insert(idL.end(), idR.rbegin(), idR.rend());
    M pre = id();
    int v = -1;
    for(int j : idL) {
      if (f(op(pre, data[j]))) {
        v = j;
        break;
      } else {
        pre = op(pre, data[j]);
      }
    }
    if (v == -1) return size;
    while(v < size) {
      if (f(op(pre, data[v << 1])))
        v = v << 1;
      else
        pre = op(pre, data[v << 1]), v = v << 1 | 1;
    }
    return v - size;
  }

  int lastTrue(int i, function<bool(const M&)> f) {
    vector<int> idL, idR;
    for(int l = size, r = (i + 1) + size; l < r; l >>= 1, r >>= 1) {
      if (l & 1) idL.emplace_back(l++);
      if (r & 1) idR.emplace_back(--r);
    }
    idR.insert(idR.end(), idL.rbegin(), idL.rend());
    M suf = id();
    int v = -1;
    for(int j : idR) {
      if (f(op(data[j], suf))) {
        v = j;
        break;
      } else {
        suf = op(data[j], suf);
      }
    }
    if (v == -1) return -1;
    while(v < size) {
      if (f(op(data[v << 1 | 1], suf)))
        v = v << 1 | 1;
      else
        suf = op(data[v << 1 | 1], suf), v = v << 1;
    }
    return v - size;
  }
};
#line 1 "segtree/segmentTree.cpp"
template<class M, M(*id)(), M(*op)(const M&, const M&)>
struct segmentTree {
  int size;
  vector<M> data;

  segmentTree(int _size) : size(_size), data(2 * size, id()) {}
  segmentTree(vector<M> init) : size(ssize(init)), data(2 * size, id()) {
    ranges::copy(init, data.begin() + size);
    for(int i = size - 1; i > 0; i--)
      data[i] = op(data[i << 1], data[i << 1 | 1]);
  }

  void set(int i, M x) {
    data[i += size] = x;
    while(i >>= 1)
      data[i] = op(data[i << 1], data[i << 1 | 1]);
  }

  M get(int i) { return data[i + size]; }

  M query(int l, int r) {
    M L = id(), R = id();
    for(l += size, r += size; l < r; l >>= 1, r >>= 1) {
      if (l & 1) L = op(L, data[l++]);
      if (r & 1) R = op(data[--r], R);
    }
    return op(L, R);
  }

  //return first j in [i, size) s.t. f(op([l, j])) is true,
  //assume f(id()) is false.
  int firstTrue(int i, function<bool(const M&)> f) {
    vector<int> idL, idR;
    for(int l = i + size, r = size << 1; l < r; l >>= 1, r >>= 1) {
      if (l & 1) idL.emplace_back(l++);
      if (r & 1) idR.emplace_back(--r);
    }
    idL.insert(idL.end(), idR.rbegin(), idR.rend());
    M pre = id();
    int v = -1;
    for(int j : idL) {
      if (f(op(pre, data[j]))) {
        v = j;
        break;
      } else {
        pre = op(pre, data[j]);
      }
    }
    if (v == -1) return size;
    while(v < size) {
      if (f(op(pre, data[v << 1])))
        v = v << 1;
      else
        pre = op(pre, data[v << 1]), v = v << 1 | 1;
    }
    return v - size;
  }

  int lastTrue(int i, function<bool(const M&)> f) {
    vector<int> idL, idR;
    for(int l = size, r = (i + 1) + size; l < r; l >>= 1, r >>= 1) {
      if (l & 1) idL.emplace_back(l++);
      if (r & 1) idR.emplace_back(--r);
    }
    idR.insert(idR.end(), idL.rbegin(), idL.rend());
    M suf = id();
    int v = -1;
    for(int j : idR) {
      if (f(op(data[j], suf))) {
        v = j;
        break;
      } else {
        suf = op(data[j], suf);
      }
    }
    if (v == -1) return -1;
    while(v < size) {
      if (f(op(data[v << 1 | 1], suf)))
        v = v << 1 | 1;
      else
        suf = op(data[v << 1 | 1], suf), v = v << 1;
    }
    return v - size;
  }
};
Back to top page