結果
問題 |
No.877 Range ReLU Query
|
ユーザー |
![]() |
提出日時 | 2025-09-02 07:09:46 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 785 ms / 2,000 ms |
コード長 | 7,743 bytes |
コンパイル時間 | 3,730 ms |
コンパイル使用メモリ | 309,124 KB |
実行使用メモリ | 162,364 KB |
最終ジャッジ日時 | 2025-09-02 07:10:00 |
合計ジャッジ時間 | 13,236 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 20 |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; bool chmin(auto &a, auto b) { return a > b ? a = b, true : false; } bool chmax(auto &a, auto b) { return a < b ? a = b, true : false; } template <typename Monoid> struct segtree { using M = Monoid; using S = typename M::S; segtree() : segtree(0) {} segtree(int _n) : segtree(vector<S>(_n, M::e())) {} segtree(const vector<S> &v) : n(v.size()) { log = 1; while ((1 << log) < n) log++; sz = 1 << log; d = vector<S>(2 * sz, M::e()); for (int i = 0; i < n; i++) d[i + sz] = v[i]; for (int i = sz - 1; i >= 1; i--) update(i); } void set(int p, const S &x) { assert(0 <= p && p < n); p += sz; d[p] = x; for (int i = 1; i <= log; i++) update(p >> i); } S get(int p) const { assert(0 <= p && p < n); return d[p + sz]; } S prod(int l, int r) const { assert(0 <= l && l <= r && r <= n); l += sz; r += sz; S pl = M::e(), pr = M::e(); while (l < r) { if (l & 1) pl = M::op(pl, d[l++]); if (r & 1) pr = M::op(d[--r], pr); l >>= 1; r >>= 1; } return M::op(pl, pr); } S all_prod() const { return d[1]; } template<typename C> int max_right(int l, const C &check) const { assert(0 <= l && l <= n); assert(check(M::e())); if (l == n) return l; l += sz; S p = M::e(); do { while (!(l & 1)) l >>= 1; S np = M::op(p, d[l]); if (!check(np)) { while (l < sz) { l <<= 1; np = M::op(p, d[l]); if (check(np)) { p = np; l++; } } return l - sz; } p = np; l++; } while ((l & -l) != l); return n; } template<typename C> int max_right(const C &check) const { return max_right(0, check); } template<typename C> int min_left(int r, const C &check) const { assert(0 <= r && r <= n); assert(check(M::e())); if (r == 0) return r; r += sz; S p = M::e(); do { r--; while (r > 1 && r & 1) r >>= 1; S np = M::op(d[r], p); if (!check(np)) { while (r < sz) { (r <<= 1)++; np = M::op(d[r], p); if (check(np)) { p = np; r--; } } return r + 1 - sz; } p = np; } while ((r & -r) != r); return 0; } template<typename C> int min_left(const C &check) const { return min_left(n, check); } private: int n, log, sz; vector<S> d; void update(int p) { d[p] = M::op(d[2 * p], d[2 * p + 1]); } }; template<typename Monoid, typename T = int> struct range_tree { using M = Monoid; using S = typename M::S; range_tree(int _n = 0) : n(-1) { pts.reserve(_n); } range_tree(const vector<tuple<T, T, S>> &p) : n(-1), pts(p) {} void add_point(T x, T y, const S &w = M::e()) { pts.emplace_back(x, y, w); } void set(T x, T y, const S &w) { build(); int i = lower_bound(xs.begin(), xs.end(), x) - xs.begin(); assert(xs[i] == x); i += sz; int j = lower_bound(ys[i].begin(), ys[i].end(), y) - ys[i].begin(); segs[i].set(j, w); while (i >>= 1) { int j = lower_bound(ys[i].begin(), ys[i].end(), y) - ys[i].begin(); segs[i].set(j, M::op(get_val(2 * i, y), get_val(2 * i + 1, y))); } } S get(T x, T y) { build(); int i = lower_bound(xs.begin(), xs.end(), x) - xs.begin(); if (i >= (int)xs.size() || xs[i] != x) return M::e(); i += sz; int j = lower_bound(ys[i].begin(), ys[i].end(), y) - ys[i].begin(); if (j >= (int)ys[i].size() || ys[i][j] != y) return M::e(); return segs[i].get(j); } S prod(T xl, T yl, T xr, T yr) { build(); int il = lower_bound(xs.begin(), xs.end(), xl) - xs.begin(); int ir = lower_bound(xs.begin(), xs.end(), xr) - xs.begin(); il += sz; ir += sz; S p = M::e(); while (il < ir) { if (il & 1) p = M::op(p, inner_prod(il++, yl, yr)); if (ir & 1) p = M::op(p, inner_prod(--ir, yl, yr)); il >>= 1; ir >>= 1; } return p; } private: int n, sz; vector<tuple<T, T, S>> pts; vector<T> xs; vector<vector<T>> ys; vector<vector<pair<T, S>>> ws; vector<segtree<M>> segs; S get_val(int i, T y) { int j = lower_bound(ys[i].begin(), ys[i].end(), y) - ys[i].begin(); return j < (int)ys[i].size() && ys[i][j] == y ? segs[i].get(j) : M::e(); } S inner_prod(int i, T yl, T yr) { int jl = lower_bound(ys[i].begin(), ys[i].end(), yl) - ys[i].begin(); int jr = lower_bound(ys[i].begin(), ys[i].end(), yr) - ys[i].begin(); return segs[i].prod(jl, jr); } void build() { if (n != -1) return; for (const auto &[x, y, w] : pts) { xs.emplace_back(x); } sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(), xs.end()), xs.end()); n = xs.size(); sz = 1; while (sz < n) sz <<= 1; ys = vector<vector<T>>(2 * sz); ws = vector<vector<pair<T, S>>>(2 * sz); segs = vector<segtree<M>>(2 * sz); for (const auto &[x, y, w] : pts) { int p = lower_bound(xs.begin(), xs.end(), x) - xs.begin(); p += sz; ys[p].emplace_back(y); ws[p].emplace_back(y, w); } for (int i = sz; i < sz + n; i++) { sort(ys[i].begin(), ys[i].end()); ys[i].erase(unique(ys[i].begin(), ys[i].end()), ys[i].end()); vector<S> v(ys[i].size(), M::e()); for (const auto &[y, w] : ws[i]) { int j = lower_bound(ys[i].begin(), ys[i].end(), y) - ys[i].begin(); v[j] = M::op(v[j], w); ws[i >> 1].emplace_back(y, w); } segs[i] = segtree<M>(v); } for (int i = sz - 1; i >= 1; i--) { const auto &yl = ys[2 * i]; const auto &yr = ys[2 * i + 1]; merge(yl.begin(), yl.end(), yr.begin(), yr.end(), back_inserter(ys[i])); ys[i].erase(unique(ys[i].begin(), ys[i].end()), ys[i].end()); vector<S> v(ys[i].size(), M::e()); for (const auto &[y, w] : ws[i]) { int j = lower_bound(ys[i].begin(), ys[i].end(), y) - ys[i].begin(); v[j] = M::op(v[j], w); ws[i >> 1].emplace_back(y, w); } segs[i] = segtree<M>(v); } } }; struct Monoid { using S = pair<ll, int>; static S op(S a, S b) { ll sum = a.first + b.first; ll cnt = a.second + b.second; return {sum, cnt}; } static S e() { return {0, 0}; } }; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; range_tree<Monoid> RT(N); for (int i = 0, A; i < N; i++) { cin >> A; RT.add_point(i, A, {A, 1}); } while (Q--) { int t, l, r, x; cin >> t >> l >> r >> x; l--; auto [val, cnt] = RT.prod(l, x, r, 1 << 30); val -= (ll)cnt * x; cout << val << '\n'; } }