This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub tko919/library
#include "DataStructure/rangelinearaddrangemin.hpp"
#pragma once struct RangeLinearAddRangeMin { RangeLinearAddRangeMin() {} template <typename T> RangeLinearAddRangeMin(vector<T> &a) { n = 1, height = 0; while (n < SZ(a)) n <<= 1, height++; base.resize(n * 2); lazy.resize(n * 2); bridges.resize(n * 2); rep(i, n, n * 2) base[i] = P(i - n, 1000000000000LL); rep(i, 0, SZ(a)) base[i + n] = P(i, a[i]); rep(i, 0, n * 2) lazy[i] = Linear{0, 0}; rep(i, n, n * 2) bridges[i] = {base[i], base[i]}; for (int i = n - 1; i >= 1; i--) find(i); } void update(int L, int R, ll a, ll b) { int lb = L + n, rb = R + n; while (lb < rb) { if (lb & 1) { lazy[lb] = merge(lazy[lb], Linear{a, b}); lb++; } lb >>= 1; if (rb & 1) { rb--; lazy[rb] = merge(lazy[rb], Linear{a, b}); } rb >>= 1; } lb = L + n, rb = R + n; for (int i = 1; i <= height; i++) { if (((lb >> i) << i) != lb) find(lb >> i); if (((rb >> i) << i) != rb) find((rb - 1) >> i); } } ll query(int L, int R) { int lb = L + n, rb = R + n; ll ret = INF; while (lb < rb) { if (lb & 1) { chmin(ret, subtree(lb)); lb++; } lb >>= 1; if (rb & 1) { rb--; chmin(ret, subtree(rb)); } rb >>= 1; } return ret; } private: struct P { ll x, y; P(ll _x = 0, ll _y = 0) : x(_x), y(_y) {} P operator+(const P &p) const { return P(x + p.x, y + p.y); } P operator-(const P &p) const { return P(x - p.x, y - p.y); } bool operator<(const P &p) const { return (y != p.y ? y < p.y : x < p.x); } bool operator==(const P &p) const { return (x == p.x and y == p.y); } bool operator!=(const P &p) const { return (x != p.x or y != p.y); } }; i128 cross(const P &a, const P &b) { return i128(a.x) * b.y - i128(a.y) * b.x; } int n, height; using Linear = pair<ll, ll>; using B = pair<P, P>; vector<P> base; vector<Linear> lazy; vector<B> bridges; void find(int i) { if (i >= n) return; Linear offset = {0, 0}; for (int x = i; x; x >>= 1) offset = merge(offset, lazy[x]); int lb = i * 2, rb = i * 2 + 1; int border = rb; while (border < n) border <<= 1; border -= n; Linear Ladd = lazy[lb], Radd = lazy[rb]; for (;;) { // cerr<<i<<' '<<lb<<' '<<rb<<'\n'; if (lb >= n and rb >= n) break; P a = bridges[lb].first, b = bridges[lb].second; P c = bridges[rb].first, d = bridges[rb].second; a = apply(a, offset); b = apply(b, offset); c = apply(c, offset); d = apply(d, offset); a = apply(a, Ladd); b = apply(b, Ladd); c = apply(c, Radd); d = apply(d, Radd); if (a != b and cross(b - a, c - a) < 0) { lb = lb * 2; Ladd = merge(Ladd, lazy[lb]); } else if (c != d and cross(c - b, d - b) < 0) { rb = rb * 2 + 1; Radd = merge(Radd, lazy[rb]); } else if (a == b) { rb = rb * 2; Radd = merge(Radd, lazy[rb]); } else if (c == d) { lb = lb * 2 + 1; Ladd = merge(Ladd, lazy[lb]); } else { i128 c1 = cross(b - a, d - c); i128 c2 = cross(b - a, b - c); bool side; if (c1 == 0 and c2 == 0) side = (c.x < border); else side = (c.x * c1 + (d.x - c.x) * c2 < c1 * border); if (side) { lb = lb * 2 + 1; Ladd = merge(Ladd, lazy[lb]); } else { rb = rb * 2; Radd = merge(Radd, lazy[rb]); } } } bridges[i] = {apply(base[lb], Ladd), apply(base[rb], Radd)}; } ll subtree(int i) { Linear add = {0, 0}; for (int x = i; x; x >>= 1) add = merge(add, lazy[x]); while (i < n) { if (apply(bridges[i].first, add).y < apply(bridges[i].second, add).y) i = i * 2; else i = i * 2 + 1; add = merge(add, lazy[i]); } P ret = apply(base[i], add); return ret.y; } Linear merge(Linear a, Linear b) { a.first += b.first; a.second += b.second; return a; } P apply(P a, Linear b) { a.y += a.x * b.first + b.second; return a; } }; /** * @brief Range Linear Add Range Min */
#line 2 "DataStructure/rangelinearaddrangemin.hpp" struct RangeLinearAddRangeMin { RangeLinearAddRangeMin() {} template <typename T> RangeLinearAddRangeMin(vector<T> &a) { n = 1, height = 0; while (n < SZ(a)) n <<= 1, height++; base.resize(n * 2); lazy.resize(n * 2); bridges.resize(n * 2); rep(i, n, n * 2) base[i] = P(i - n, 1000000000000LL); rep(i, 0, SZ(a)) base[i + n] = P(i, a[i]); rep(i, 0, n * 2) lazy[i] = Linear{0, 0}; rep(i, n, n * 2) bridges[i] = {base[i], base[i]}; for (int i = n - 1; i >= 1; i--) find(i); } void update(int L, int R, ll a, ll b) { int lb = L + n, rb = R + n; while (lb < rb) { if (lb & 1) { lazy[lb] = merge(lazy[lb], Linear{a, b}); lb++; } lb >>= 1; if (rb & 1) { rb--; lazy[rb] = merge(lazy[rb], Linear{a, b}); } rb >>= 1; } lb = L + n, rb = R + n; for (int i = 1; i <= height; i++) { if (((lb >> i) << i) != lb) find(lb >> i); if (((rb >> i) << i) != rb) find((rb - 1) >> i); } } ll query(int L, int R) { int lb = L + n, rb = R + n; ll ret = INF; while (lb < rb) { if (lb & 1) { chmin(ret, subtree(lb)); lb++; } lb >>= 1; if (rb & 1) { rb--; chmin(ret, subtree(rb)); } rb >>= 1; } return ret; } private: struct P { ll x, y; P(ll _x = 0, ll _y = 0) : x(_x), y(_y) {} P operator+(const P &p) const { return P(x + p.x, y + p.y); } P operator-(const P &p) const { return P(x - p.x, y - p.y); } bool operator<(const P &p) const { return (y != p.y ? y < p.y : x < p.x); } bool operator==(const P &p) const { return (x == p.x and y == p.y); } bool operator!=(const P &p) const { return (x != p.x or y != p.y); } }; i128 cross(const P &a, const P &b) { return i128(a.x) * b.y - i128(a.y) * b.x; } int n, height; using Linear = pair<ll, ll>; using B = pair<P, P>; vector<P> base; vector<Linear> lazy; vector<B> bridges; void find(int i) { if (i >= n) return; Linear offset = {0, 0}; for (int x = i; x; x >>= 1) offset = merge(offset, lazy[x]); int lb = i * 2, rb = i * 2 + 1; int border = rb; while (border < n) border <<= 1; border -= n; Linear Ladd = lazy[lb], Radd = lazy[rb]; for (;;) { // cerr<<i<<' '<<lb<<' '<<rb<<'\n'; if (lb >= n and rb >= n) break; P a = bridges[lb].first, b = bridges[lb].second; P c = bridges[rb].first, d = bridges[rb].second; a = apply(a, offset); b = apply(b, offset); c = apply(c, offset); d = apply(d, offset); a = apply(a, Ladd); b = apply(b, Ladd); c = apply(c, Radd); d = apply(d, Radd); if (a != b and cross(b - a, c - a) < 0) { lb = lb * 2; Ladd = merge(Ladd, lazy[lb]); } else if (c != d and cross(c - b, d - b) < 0) { rb = rb * 2 + 1; Radd = merge(Radd, lazy[rb]); } else if (a == b) { rb = rb * 2; Radd = merge(Radd, lazy[rb]); } else if (c == d) { lb = lb * 2 + 1; Ladd = merge(Ladd, lazy[lb]); } else { i128 c1 = cross(b - a, d - c); i128 c2 = cross(b - a, b - c); bool side; if (c1 == 0 and c2 == 0) side = (c.x < border); else side = (c.x * c1 + (d.x - c.x) * c2 < c1 * border); if (side) { lb = lb * 2 + 1; Ladd = merge(Ladd, lazy[lb]); } else { rb = rb * 2; Radd = merge(Radd, lazy[rb]); } } } bridges[i] = {apply(base[lb], Ladd), apply(base[rb], Radd)}; } ll subtree(int i) { Linear add = {0, 0}; for (int x = i; x; x >>= 1) add = merge(add, lazy[x]); while (i < n) { if (apply(bridges[i].first, add).y < apply(bridges[i].second, add).y) i = i * 2; else i = i * 2 + 1; add = merge(add, lazy[i]); } P ret = apply(base[i], add); return ret.y; } Linear merge(Linear a, Linear b) { a.first += b.first; a.second += b.second; return a; } P apply(P a, Linear b) { a.y += a.x * b.first + b.second; return a; } }; /** * @brief Range Linear Add Range Min */