This documentation is automatically generated by online-judge-tools/verification-helper
#include "data_structure/offline_segtree_2d.hpp"
可換モノイドについて、1点更新、長方形領域クエリを行えるデータ構造。クエリ先読みにより、必要な部分だけ作ることでメモリ使用量を減らして点の座標が$10^9$とかでも使える。
offline_segtree_2d<S, op, e> seg2d;
S
, op
, e
は可換モノイドとする。
$(i,j)$ を追加する。
クエリ先読み後(pre_set後)、セグ木を構築する。
$(i, j)$ を $x$ に更新する。O(\log H)
$(i, j)$ の値を返す。 $O(1)$
$[l, r) \times [d, u)$ の領域に対してクエリを処理する $O(\log H \log W)$
#pragma once
#include <algorithm>
#include <vector>
/*
reference: https://blog.hamayanhamayan.com/entry/2017/12/09/015937
*/
#include "../data_structure/compress.hpp"
#include "../data_structure/segtree.hpp"
namespace ebi {
template <class S, S (*op)(S, S), S (*e)()> struct offline_segtree_2d {
offline_segtree_2d() = default;
void pre_set(int i, int j) {
ps.emplace_back(i, j);
}
void pre_set(std::pair<int, int> p) {
ps.emplace_back(p);
}
void build() {
for (auto [x, y] : ps) {
xs.add(x);
}
xs.build();
while (sz < xs.size()) sz <<= 1;
ys.resize(2 * sz);
for (auto [x, y] : ps) {
int i = xs.get(x) + sz;
ys[i].add(y);
while (i > 1) {
i >>= 1;
ys[i].add(y);
}
}
for (int i = 0; i < 2 * sz; i++) {
ys[i].build();
data.emplace_back(ys[i].size());
}
}
void set(int i, int j, S val) {
i = xs.get(i);
i += sz;
data[i].set(ys[i].get(j), val);
while (i > 1) {
i >>= 1;
S res = e();
if (ys[2 * i].find(j)) {
res = op(res, data[2 * i].get(ys[2 * i].get(j)));
}
if (ys[2 * i + 1].find(j)) {
res = op(res, data[2 * i + 1].get(ys[2 * i + 1].get(j)));
}
data[i].set(ys[i].get(j), res);
}
}
S get(int i, int j) const {
i = xs.get(i) + sz;
return data[i].get(ys[i].get(j));
}
S prod(int l, int d, int r, int u) const {
l = xs.get(l) + sz;
r = xs.get(r) + sz;
S res = e();
while (l < r) {
if (l & 1) {
res = op(res, data[l].prod(ys[l].get(d), ys[l].get(u)));
l++;
}
if (r & 1) {
r--;
res = op(data[r].prod(ys[r].get(d), ys[r].get(u)), res);
}
l >>= 1;
r >>= 1;
}
return res;
}
private:
int sz = 1;
std::vector<std::pair<int, int>> ps;
compress<int> xs;
std::vector<compress<int>> ys;
std::vector<segtree<S, op, e>> data;
};
} // namespace ebi
#line 2 "data_structure/offline_segtree_2d.hpp"
#include <algorithm>
#include <vector>
/*
reference: https://blog.hamayanhamayan.com/entry/2017/12/09/015937
*/
#line 2 "data_structure/compress.hpp"
#line 4 "data_structure/compress.hpp"
#include <cassert>
#line 6 "data_structure/compress.hpp"
namespace ebi {
template <class T> struct compress {
private:
std::vector<T> cp;
public:
compress() = default;
compress(std::vector<T> cp_) : cp(cp_) {
build();
}
void build() {
std::sort(cp.begin(), cp.end());
cp.erase(std::unique(cp.begin(), cp.end()), cp.end());
}
void add(const T &val) {
cp.emplace_back(val);
}
int get(const T &val) const {
return std::lower_bound(cp.begin(), cp.end(), val) - cp.begin();
}
int size() const {
return cp.size();
}
bool find(const T &val) const {
auto itr = std::lower_bound(cp.begin(), cp.end(), val);
if (itr == cp.end())
return false;
else
return *itr == val;
}
T val(int idx) const {
assert(0 <= idx && idx < (int)cp.size());
return cp[idx];
}
};
} // namespace ebi
#line 2 "data_structure/segtree.hpp"
#line 5 "data_structure/segtree.hpp"
namespace ebi {
template <class S, S (*op)(S, S), S (*e)()> struct segtree {
private:
int n;
int sz;
std::vector<S> data;
void update(int i) {
data[i] = op(data[2 * i], data[2 * i + 1]);
}
public:
segtree(int n_) : segtree(std::vector<S>(n_, e())) {}
segtree(const std::vector<S> &v) : n((int)v.size()), sz(1) {
while (sz < n) sz *= 2;
data = std::vector<S>(2 * sz, e());
for (int i = 0; i < n; i++) {
data[sz + i] = v[i];
}
for (int i = sz - 1; i >= 1; i--) update(i);
}
void set(int p, S x) {
assert(0 <= p && p < n);
p += sz;
data[p] = x;
while (p > 1) {
p >>= 1;
update(p);
}
}
S get(int p) const {
assert(0 <= p && p < n);
return data[p + sz];
}
S prod(int l, int r) const {
assert(0 <= l && l <= r && r <= n);
S sml = e(), smr = e();
l += sz;
r += sz;
while (l < r) {
if (l & 1) sml = op(sml, data[l++]);
if (r & 1) smr = op(data[--r], smr);
l >>= 1;
r >>= 1;
}
return op(sml, smr);
}
S all_prod() const {
return data[1];
}
template <class F> int max_right(int l, F f) const {
assert(0 <= l && l < n);
assert(f(e()));
if (l == n) return n;
l += sz;
S sm = e();
do {
while (l % 2 == 0) l >>= 1;
if (!f(op(sm, data[l]))) {
while (l < sz) {
l = 2 * l;
if (f(op(sm, data[l]))) {
sm = op(sm, data[l]);
l++;
}
}
return l - sz;
}
sm = op(sm, data[l]);
l++;
} while ((l & -l) != l);
return n;
}
template <class F> int min_left(int r, F f) const {
assert(0 <= r && r <= n);
assert(f(e()));
if (r == 0) return 0;
r += sz;
S sm = e();
do {
r--;
while (r > 1 && (r % 2)) r >>= 1;
if (!f(op(data[r], sm))) {
while (r < sz) {
r = 2 * r + 1;
if (f(op(data[r], sm))) {
sm = op(data[r], sm);
r--;
}
}
return r + 1 - sz;
}
sm = op(data[r], sm);
} while ((r & -r) != r);
return 0;
}
S operator[](int p) const {
return data[sz + p];
}
};
} // namespace ebi
#line 12 "data_structure/offline_segtree_2d.hpp"
namespace ebi {
template <class S, S (*op)(S, S), S (*e)()> struct offline_segtree_2d {
offline_segtree_2d() = default;
void pre_set(int i, int j) {
ps.emplace_back(i, j);
}
void pre_set(std::pair<int, int> p) {
ps.emplace_back(p);
}
void build() {
for (auto [x, y] : ps) {
xs.add(x);
}
xs.build();
while (sz < xs.size()) sz <<= 1;
ys.resize(2 * sz);
for (auto [x, y] : ps) {
int i = xs.get(x) + sz;
ys[i].add(y);
while (i > 1) {
i >>= 1;
ys[i].add(y);
}
}
for (int i = 0; i < 2 * sz; i++) {
ys[i].build();
data.emplace_back(ys[i].size());
}
}
void set(int i, int j, S val) {
i = xs.get(i);
i += sz;
data[i].set(ys[i].get(j), val);
while (i > 1) {
i >>= 1;
S res = e();
if (ys[2 * i].find(j)) {
res = op(res, data[2 * i].get(ys[2 * i].get(j)));
}
if (ys[2 * i + 1].find(j)) {
res = op(res, data[2 * i + 1].get(ys[2 * i + 1].get(j)));
}
data[i].set(ys[i].get(j), res);
}
}
S get(int i, int j) const {
i = xs.get(i) + sz;
return data[i].get(ys[i].get(j));
}
S prod(int l, int d, int r, int u) const {
l = xs.get(l) + sz;
r = xs.get(r) + sz;
S res = e();
while (l < r) {
if (l & 1) {
res = op(res, data[l].prod(ys[l].get(d), ys[l].get(u)));
l++;
}
if (r & 1) {
r--;
res = op(data[r].prod(ys[r].get(d), ys[r].get(u)), res);
}
l >>= 1;
r >>= 1;
}
return res;
}
private:
int sz = 1;
std::vector<std::pair<int, int>> ps;
compress<int> xs;
std::vector<compress<int>> ys;
std::vector<segtree<S, op, e>> data;
};
} // namespace ebi