This documentation is automatically generated by online-judge-tools/verification-helper
#include "structure/rectangle_apply_point_get.hpp"長方形領域に作用素を掛け、一点に掛かっている作用素を取得するデータ構造です。
座標範囲を先に指定し、その範囲内の長方形作用と一点取得をオンラインに処理できます。
作用素 F はモノイドとして扱います。
F composition(F f, F g)
F id()
composition(f, g) は ACL の lazy_segtree と同じく、作用 g の後に作用 f を適用する合成、id() は単位元です。
rectangle_apply_point_get<F, composition, id, T = int>(T xl, T xr, T yl, T yr)
座標範囲 $[xl, xr) \times [yl, yr)$ を指定する。
T は座標の型です。
void apply(T l, T r, T d, T u, F f)
領域 $[l, r) \times [d, u)$ に作用 f を掛ける。
座標範囲の幅を $X = xr - xl, Y = yr - yl$ として
新しく作られる内部ノード数も $O(\log X \log Y)$。
F get(T x, T y)
点 (x, y) に掛かっている作用素の合成を返す。
座標範囲の幅を $X = xr - xl, Y = yr - yl$ として
内部ノードは作らない。
#ifndef HARUILIB_STRUCTURE_RECTANGLE_APPLY_POINT_GET_HPP
#define HARUILIB_STRUCTURE_RECTANGLE_APPLY_POINT_GET_HPP
#include <cassert>
#include <vector>
template <class F, F (*composition)(F, F), F (*id)(), class T = int>
struct rectangle_apply_point_get {
rectangle_apply_point_get(T xl, T xr, T yl, T yr)
: xl(xl), xr(xr), yl(yl), yr(yr), root(-1) {
assert(xl < xr);
assert(yl < yr);
root = new_x_node();
}
void apply(T l, T r, T d, T u, F f) {
assert(xl <= l && l <= r && r <= xr);
assert(yl <= d && d <= u && u <= yr);
apply_x(root, xl, xr, l, r, d, u, f);
}
F get(T x, T y) const {
assert(xl <= x && x < xr);
assert(yl <= y && y < yr);
return get_x(root, xl, xr, x, y);
}
private:
struct XNode {
int left, right, y_root;
};
struct YNode {
int left, right;
F val;
};
int new_x_node() {
xs.push_back({-1, -1, -1});
return (int)xs.size() - 1;
}
int new_y_node() {
ys.push_back({-1, -1, id()});
return (int)ys.size() - 1;
}
void apply_x(int k, T nl, T nr, T ql, T qr, T qd, T qu, F f) {
if (qr <= nl || nr <= ql) return;
if (ql <= nl && nr <= qr) {
xs[k].y_root = apply_y(xs[k].y_root, yl, yr, qd, qu, f);
return;
}
T mid = nl + (nr - nl) / 2;
if (ql < mid) {
if (xs[k].left == -1) {
int child = new_x_node();
xs[k].left = child;
}
apply_x(xs[k].left, nl, mid, ql, qr, qd, qu, f);
}
if (mid < qr) {
if (xs[k].right == -1) {
int child = new_x_node();
xs[k].right = child;
}
apply_x(xs[k].right, mid, nr, ql, qr, qd, qu, f);
}
}
int apply_y(int k, T nl, T nr, T ql, T qr, F f) {
if (qr <= nl || nr <= ql) return k;
if (k == -1) k = new_y_node();
if (ql <= nl && nr <= qr) {
ys[k].val = composition(f, ys[k].val);
return k;
}
T mid = nl + (nr - nl) / 2;
if (ql < mid) ys[k].left = apply_y(ys[k].left, nl, mid, ql, qr, f);
if (mid < qr) ys[k].right = apply_y(ys[k].right, mid, nr, ql, qr, f);
return k;
}
F get_x(int k, T nl, T nr, T x, T y) const {
if (k == -1) return id();
F res = get_y(xs[k].y_root, yl, yr, y);
if (nr - nl == 1) return res;
T mid = nl + (nr - nl) / 2;
if (x < mid) return composition(get_x(xs[k].left, nl, mid, x, y), res);
return composition(get_x(xs[k].right, mid, nr, x, y), res);
}
F get_y(int k, T nl, T nr, T y) const {
if (k == -1) return id();
F res = ys[k].val;
if (nr - nl == 1) return res;
T mid = nl + (nr - nl) / 2;
if (y < mid) return composition(get_y(ys[k].left, nl, mid, y), res);
return composition(get_y(ys[k].right, mid, nr, y), res);
}
T xl, xr, yl, yr;
int root;
std::vector<XNode> xs;
std::vector<YNode> ys;
};
#endif // HARUILIB_STRUCTURE_RECTANGLE_APPLY_POINT_GET_HPP#line 1 "structure/rectangle_apply_point_get.hpp"
#include <cassert>
#include <vector>
template <class F, F (*composition)(F, F), F (*id)(), class T = int>
struct rectangle_apply_point_get {
rectangle_apply_point_get(T xl, T xr, T yl, T yr)
: xl(xl), xr(xr), yl(yl), yr(yr), root(-1) {
assert(xl < xr);
assert(yl < yr);
root = new_x_node();
}
void apply(T l, T r, T d, T u, F f) {
assert(xl <= l && l <= r && r <= xr);
assert(yl <= d && d <= u && u <= yr);
apply_x(root, xl, xr, l, r, d, u, f);
}
F get(T x, T y) const {
assert(xl <= x && x < xr);
assert(yl <= y && y < yr);
return get_x(root, xl, xr, x, y);
}
private:
struct XNode {
int left, right, y_root;
};
struct YNode {
int left, right;
F val;
};
int new_x_node() {
xs.push_back({-1, -1, -1});
return (int)xs.size() - 1;
}
int new_y_node() {
ys.push_back({-1, -1, id()});
return (int)ys.size() - 1;
}
void apply_x(int k, T nl, T nr, T ql, T qr, T qd, T qu, F f) {
if (qr <= nl || nr <= ql) return;
if (ql <= nl && nr <= qr) {
xs[k].y_root = apply_y(xs[k].y_root, yl, yr, qd, qu, f);
return;
}
T mid = nl + (nr - nl) / 2;
if (ql < mid) {
if (xs[k].left == -1) {
int child = new_x_node();
xs[k].left = child;
}
apply_x(xs[k].left, nl, mid, ql, qr, qd, qu, f);
}
if (mid < qr) {
if (xs[k].right == -1) {
int child = new_x_node();
xs[k].right = child;
}
apply_x(xs[k].right, mid, nr, ql, qr, qd, qu, f);
}
}
int apply_y(int k, T nl, T nr, T ql, T qr, F f) {
if (qr <= nl || nr <= ql) return k;
if (k == -1) k = new_y_node();
if (ql <= nl && nr <= qr) {
ys[k].val = composition(f, ys[k].val);
return k;
}
T mid = nl + (nr - nl) / 2;
if (ql < mid) ys[k].left = apply_y(ys[k].left, nl, mid, ql, qr, f);
if (mid < qr) ys[k].right = apply_y(ys[k].right, mid, nr, ql, qr, f);
return k;
}
F get_x(int k, T nl, T nr, T x, T y) const {
if (k == -1) return id();
F res = get_y(xs[k].y_root, yl, yr, y);
if (nr - nl == 1) return res;
T mid = nl + (nr - nl) / 2;
if (x < mid) return composition(get_x(xs[k].left, nl, mid, x, y), res);
return composition(get_x(xs[k].right, mid, nr, x, y), res);
}
F get_y(int k, T nl, T nr, T y) const {
if (k == -1) return id();
F res = ys[k].val;
if (nr - nl == 1) return res;
T mid = nl + (nr - nl) / 2;
if (y < mid) return composition(get_y(ys[k].left, nl, mid, y), res);
return composition(get_y(ys[k].right, mid, nr, y), res);
}
T xl, xr, yl, yr;
int root;
std::vector<XNode> xs;
std::vector<YNode> ys;
};