Submission #1253835

#TimeUsernameProblemLanguageResultExecution timeMemory
1253835ankiteTriple Jump (JOI19_jumps)C++20
0 / 100
23 ms26948 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; static const ll NEGINF = (ll)-4e18; struct Node { // mx1 = maximum A[i] in the segment // mx2 = maximum A[i] + A[j] for i<j in the segment // mxAdj = maximum A[i] + A[i+1] for adjacent pair in the segment // ans = maximum A[a]+A[b]+A[c] with a<b<c and (b−a) ≤ (c−b) in the segment ll mx1, mx2, mxAdj, ans; Node() : mx1(NEGINF) , mx2(NEGINF) , mxAdj(NEGINF) , ans(NEGINF) {} }; int N, Q; vector<ll> A; vector<Node> seg; // Merge two child‐nodes L and R whose intervals are // consecutive: [l..mid] and [mid+1..r] Node mergeNode(const Node &L, const Node &R, int mid) { Node res; // best single res.mx1 = max(L.mx1, R.mx1); // best two‐sum (anywhere) res.mx2 = max({ L.mx2, R.mx2, L.mx1 + R.mx1 }); // best adjacent‐pair sum // either fully in L, fully in R, or straddling the boundary at mid/mid+1 res.mxAdj = max({ L.mxAdj, R.mxAdj, A[mid] + A[mid+1] }); // best triple: // either entirely in L (L.ans) // or entirely in R (R.ans) // or two in L (an adjacent pair anywhere in L) // plus best single in R // or one in L (best single in L) // plus two adjacent in R ll cross1 = (L.mxAdj > NEGINF && R.mx1 > NEGINF ? L.mxAdj + R.mx1 : NEGINF); ll cross2 = (L.mx1 > NEGINF && R.mxAdj > NEGINF ? L.mx1 + R.mxAdj : NEGINF); res.ans = max({ L.ans, R.ans, cross1, cross2 }); return res; } // build segment tree on [l..r] at index p void build(int p, int l, int r) { if (l == r) { // leaf seg[p].mx1 = A[l]; seg[p].mx2 = NEGINF; seg[p].mxAdj = NEGINF; seg[p].ans = NEGINF; return; } int mid = (l + r) >> 1; build(p<<1, l, mid); build(p<<1|1, mid+1, r); seg[p] = mergeNode(seg[p<<1], seg[p<<1|1], mid); } // query on [ql..qr], node at p covers [l..r] Node query(int p, int l, int r, int ql, int qr) { if (qr < l || r < ql) { // completely outside return Node(); } if (ql <= l && r <= qr) { // fully inside return seg[p]; } int mid = (l + r) >> 1; Node left = query(p<<1, l, mid, ql, qr); Node right = query(p<<1|1, mid+1, r, ql, qr); // if one side is empty, return the other if (left.mx1 == NEGINF) return right; if (right.mx1 == NEGINF) return left; // otherwise they are contiguous by construction return mergeNode(left, right, mid); } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin >> N; A.resize(N+1); for(int i = 1; i <= N; i++){ cin >> A[i]; } seg.assign(4*(N+1), Node()); build(1, 1, N); cin >> Q; while(Q--){ int L, R; cin >> L >> R; Node ans_node = query(1, 1, N, L, R); // ans_node.ans holds the maximum A[a]+A[b]+A[c] // under the constraint a<b<c, (b−a)≤(c−b) // in the subarray [L..R]. cout << ans_node.ans << "\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...