結果
問題 | No.2861 Slime Party |
ユーザー |
![]() |
提出日時 | 2024-07-25 20:40:20 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,998 ms / 4,000 ms |
コード長 | 5,174 bytes |
コンパイル時間 | 1,674 ms |
コンパイル使用メモリ | 96,344 KB |
最終ジャッジ日時 | 2025-02-23 18:03:16 |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 76 |
ソースコード
#include <vector>#include <iostream>#include <algorithm>using namespace std;const long long INF = 3LL << 59;class query {public:int t, a; long long b;query() : t(-1), a(-1), b(-1) {}};class node {public:int p, l, r;node() : p(-1), l(-1), r(-1) {}};class binary_tree {public:int root;vector<node> v;binary_tree(int n) : root(-1), v(vector<node>(n)) {}};binary_tree cartesian_tree(int N, const vector<long long>& A) {binary_tree T(N);vector<int> st;int pos = 0;for (int i = 0; i < N; i++) {int u = -1;while (!st.empty() && A[st.back()] < A[i]) {u = st.back();st.pop_back();}if (u != -1) {T.v[i].l = u;T.v[u].p = i;}if (!st.empty()) {T.v[i].p = st.back();T.v[st.back()].r = i;}st.push_back(i);}T.root = st[0];return T;}class segment_tree {// range add / range maxprivate:int size;vector<long long> v;vector<long long> lazy;void push(int k) {v[k] += lazy[k];if (k < size) {lazy[k * 2 + 0] += lazy[k];lazy[k * 2 + 1] += lazy[k];}lazy[k] = 0;}public:segment_tree(int n) : size(1 << (n >= 2 ? 32 - __builtin_clz(n - 1) : 0)), v(size * 2), lazy(size * 2) {}void range_add(int l, int r, long long x) {auto recur = [&](auto& self, int k, int s, int t) -> void {if (l <= s && t <= r) {lazy[k] += x;push(k);return;}push(k);if (r <= s || t <= l) {return;}self(self, k * 2 + 0, s, (s + t) / 2);self(self, k * 2 + 1, (s + t) / 2, t);v[k] = max(v[k * 2 + 0], v[k * 2 + 1]);};recur(recur, 1, 0, size);}long long range_max(int l, int r) {auto recur = [&](auto& self, int k, int s, int t) -> long long {push(k);if (l <= s && t <= r) {return v[k];}if (r <= s || t <= l) {return -INF;}long long zl = self(self, k * 2 + 0, s, (s + t) / 2);long long zr = self(self, k * 2 + 1, (s + t) / 2, t);v[k] = max(v[k * 2 + 0], v[k * 2 + 1]);return max(zl, zr);};return recur(recur, 1, 0, size);}};class heavy_light {private:int n;vector<int> par;vector<int> id;vector<int> id_vertex;vector<int> head;segment_tree seg;public:heavy_light(const vector<int>& par_) : n(par_.size()), par(par_), seg(n) {vector<vector<int> > g(n);int root = -1;for (int i = 0; i < n; i++) {if (par[i] != -1) {g[par[i]].push_back(i);} else {root = i;}}vector<int> subsize(n, 1);auto build_order = [&](auto& self, int v) -> void {for (int &i : g[v]) {self(self, i);subsize[v] += subsize[i];if (subsize[i] > subsize[g[v][0]]) {swap(g[v][0], i);}}};build_order(build_order, root);int cur = 0;id.resize(n);id_vertex.resize(n);head.resize(n);auto build_tree = [&](auto& self, int v) -> void {id[v] = cur;id_vertex[cur] = v;cur++;for (int i : g[v]) {head[i] = (i == g[v][0] ? head[v] : i);self(self, i);}};head[root] = root;build_tree(build_tree, root);}void add_vertex(int v, long long x) {seg.range_add(id[v], id[v] + 1, x);}void add_path(int v, long long x) {while (v != -1) {seg.range_add(id[head[v]], id[v] + 1, x);v = par[head[v]];}}long long get_vertex(int v) {return seg.range_max(id[v], id[v] + 1);}int query(int v, long long x) {// first unreachable ancestor from v by only passing vertex with < xwhile (v != -1) {if (seg.range_max(id[head[v]], id[v] + 1) >= x) {break;}v = par[head[v]];}if (v == -1) {return -1;}int l = id[head[v]], r = id[v] + 1;while (r - l > 1) {int m = (l + r) / 2;if (seg.range_max(m, id[v] + 1) >= x) {l = m;} else {r = m;}}return id_vertex[l];}};vector<long long> solve(int N, int Q, long long L, const vector<long long>& A, const vector<long long>& X, const vector<query>& qs) {binary_tree T = cartesian_tree(N, A);vector<int> par(N);for (int i = 0; i < N; i++) {par[i] = T.v[i].p;}heavy_light hld(par);for (int i = 0; i < N; i++) {hld.add_path(i, -X[i]);if (i != T.root) {hld.add_vertex(i, A[par[i]]);}}vector<long long> CX = X;vector<long long> ans;for (query q : qs) {if (q.t == 1) {long long d = q.b - CX[q.a];CX[q.a] = q.b;hld.add_path(q.a, -d);}if (q.t == 2) {int base = (A[q.a] < A[q.a + 1] ? q.a : q.a + 1);if (A[base] < L) {int pos = hld.query(base, L);if (pos == -1) {pos = T.root;}long long subans = hld.get_vertex(pos);ans.push_back(-(subans - (pos != T.root ? A[T.v[pos].p] : 0)) + L);} else {ans.push_back(L);}}}return ans;}int main() {cin.tie(nullptr);ios::sync_with_stdio(false);int N, Q; long long L;cin >> N >> Q >> L;vector<long long> A(N), X(N);for (int i = 0; i < N; i++) {cin >> A[i];}for (int i = 0; i < N; i++) {cin >> X[i];}vector<query> qs(Q);for (int i = 0; i < Q; i++) {cin >> qs[i].t >> qs[i].a;if (qs[i].t == 1) {cin >> qs[i].b;}qs[i].a--;}vector<long long> ans = solve(N, Q, L, A, X, qs);for (int i = 0; i < int(ans.size()); i++) {cout << ans[i] << '\n';}return 0;}