제출 #168161

#제출 시각아이디문제언어결과실행 시간메모리
168161AlexPop283단 점프 (JOI19_jumps)C++11
100 / 100
1531 ms101088 KiB
#include <bits/stdc++.h> #define dbg() cerr << #define name(x) (#x) << ": " << (x) << ' ' << // dupa 7 ore printre care 3 de somn in care ma tot gandeam de ce luasem // RTE, am ajuns la concluzia ca e din cauza stupizeniei de windows... using namespace std; struct SegmTree { struct Node { int maxv, val, lazy; Node(int maxv_ = 0, int val_ = 0, int lazy_ = 0) : maxv(maxv_), val(val_), lazy(lazy_) {} // maxv = val max on [l, r] in v // val = maximum val of jumps in [l, r] // lazy = max val to update children with }; int n; vector<int> v; vector<Node> tree; SegmTree(const vector<int> v_) : n(v_.size()), v(v_), tree(4 * n) { Build(0, 0, n - 1); } void Recalc(int node) { tree[node].val = max(tree[2 * node + 1].val, tree[2 * node + 2].val); } void Build(int node, int left, int right) { if (left == right) { tree[node].maxv = v[left]; tree[node].val = v[left]; tree[node].lazy = 0; return; } int mid = left + (right - left) / 2; Build(2 * node + 1, left, mid); Build(2 * node + 2, mid + 1, right); tree[node].maxv = max(tree[2 * node + 1].maxv, tree[2 * node + 2].maxv); Recalc(node); } void Propagate(int node, int len) { if (len == 1) return; for (int son : {2 * node + 1, 2 * node + 2}) { tree[son].lazy = max(tree[son].lazy, tree[node].lazy); tree[son].val = max(tree[son].val, tree[son].maxv + tree[son].lazy); } } void Update(int node, int left, int right, int x, int y, int val) { Propagate(node, right - left + 1); if (x <= left && right <= y) { tree[node].val = max(tree[node].val, tree[node].maxv + val); tree[node].lazy = max(tree[node].lazy, val); // dbg() "Am setat: " << name(left) name(right) name(tree[node].val) endl; return; } int mid = left + (right - left) / 2; if (x <= mid) Update(2 * node + 1, left, mid, x, y, val); if (mid < y) Update(2 * node + 2, mid + 1, right, x, y, val); Recalc(node); } int Query(int node, int left, int right, int x, int y) { Propagate(node, right - left + 1); if (x <= left && right <= y) { return tree[node].val; } int mid = left + (right - left) / 2; int ret = 0; if (x <= mid) ret = max(ret, Query(2 * node + 1, left, mid, x, y)); if (mid < y) ret = max(ret, Query(2 * node + 2, mid + 1, right, x, y)); Recalc(node); return ret; } void Update(int l, int r, int val) { if (l > r) return; // dbg() "U: " << name(l) name(r) name(val) endl; Update(0, 0, n - 1, l, r, val); } int Query(int l, int r) { // dbg() "Q: " << name(l) name(r) endl; return Query(0, 0, n - 1, l, r); } }; vector<vector<int>> GetAdd(const vector<int> &v) { int n = v.size(); vector<int> stk = {-1}, lft(n), rgt(n); for (int i = 0; i < n; ++i) { while (stk.size() > 1 && v[stk.back()] < v[i]) { rgt[stk.back()] = i; stk.pop_back(); } lft[i] = stk.back(); stk.emplace_back(i); } while (stk.size() > 1) { rgt[stk.back()] = n; stk.pop_back(); } vector<vector<int>> to_add(n); for (int i = 0; i < n; ++i) { if (lft[i] != -1) { to_add[lft[i]].emplace_back(i); } if (rgt[i] != n) { to_add[i].emplace_back(rgt[i]); } } return to_add; } int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int n; cin >> n; vector<int> v(n); for (int &x : v) { cin >> x; } int q; cin >> q; vector<vector<pair<int, int>>> qrs(n); for (int i = 0; i < q; ++i) { int l, r; cin >> l >> r; --l, --r; qrs[l].emplace_back(r, i); } auto to_add = GetAdd(v); SegmTree tree(v); vector<int> ans(q); for (int l = n - 1; l >= 0; --l) { for (int &x : to_add[l]) { tree.Update(x + x - l, n - 1, v[l] + v[x]); } for (auto &p : qrs[l]) { ans[p.second] = tree.Query(l, p.first); } } for (int &x : ans) { cout << x << '\n'; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...