Submission #1253831

#TimeUsernameProblemLanguageResultExecution timeMemory
1253831ankiteTriple Jump (JOI19_jumps)C++20
0 / 100
213 ms298652 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; struct Node { ll best; // best triple A[a]+A[b]+A[c] ll mx; // max A[x] vector<ll> L; // L[d] = best A[a]+A[a+d] in left half vector<ll> R; // R[d] = best A[c-d]+A[c] in right half Node(): best(0), mx(0) {} }; int N; vector<ll> A; vector<Node> seg; // Merge two nodes a=[l..m], b=[m+1..r] into res=[l..r] Node merge(const Node &a, const Node &b) { int nl = (int)a.L.size() + (int)a.R.size() + 1; // not actually used Node res; res.mx = max(a.mx, b.mx); // 1) best entirely in one side res.best = max(a.best, b.best); // Prepare L for res: pairs entirely in left child or crossing int lenL = a.L.size() + 1; // interval length of left child int lenR = b.R.size() + 1; // length of right child int len = lenL + lenR; res.L.assign(len, LLONG_MIN); res.R.assign(len, LLONG_MIN); // 2) copy old L pairs from a for (int d = 1; d < (int)a.L.size(); d++) res.L[d] = max(res.L[d], a.L[d]); // 3) pairs entirely in b but re‐indexed to global for (int d = 1; d < (int)b.L.size(); d++) res.L[d + lenL] = max(res.L[d + lenL], b.L[d]); // 4) similarly for R for (int d = 1; d < (int)b.R.size(); d++) res.R[d] = max(res.R[d], b.R[d]); for (int d = 1; d < (int)a.R.size(); d++) res.R[d + lenR] = max(res.R[d + lenR], a.R[d]); // 5) now handle triples that cross—i.e. a pair from left child of offset d1, // a single from the boundary, and a pair from right child of offset d2, // subject to d1 <= d2. // Actually it suffices to scan all d where both res.L[d], res.R[d] are valid: for (int d = 1; d < len; d++) { if (res.L[d] > LLONG_MIN/2 && res.R[d] > LLONG_MIN/2) { res.best = max(res.best, res.L[d] + res.R[d] - /*A[b] counted twice*/ 0); } } // Finally, any triple using two from one side and one singleton from the other? // Actually those are already included in a.best or b.best, or in the scan above. return res; } void build(int idx, int l, int r) { if (l == r) { seg[idx].best = 0; // no triple in a single point seg[idx].mx = A[l]; seg[idx].L = seg[idx].R = vector<ll>(2, LLONG_MIN); // no valid d=1 pair in a single point return; } int m = (l + r) >> 1; build(idx<<1, l, m); build(idx<<1|1, m+1, r); seg[idx] = merge(seg[idx<<1], seg[idx<<1|1]); } Node query(int idx, int l, int r, int ql, int qr) { if (ql <= l && r <= qr) return seg[idx]; int m = (l + r) >> 1; if (qr <= m) return query(idx<<1, l, m, ql, qr); if (ql > m) return query(idx<<1|1, m+1, r, ql, qr); return merge( query(idx<<1, l, m, ql, qr), query(idx<<1|1, m+1, r, ql, qr) ); } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); int Q; cin >> N; A.resize(N+1); for (int i = 1; i <= N; i++) cin >> A[i]; seg.resize(4*(N+1)); build(1, 1, N); cin >> Q; while (Q--) { int L, R; cin >> L >> R; auto ans = query(1, 1, N, L, R); cout << ans.best << "\n"; } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...