Submission #168161

#TimeUsernameProblemLanguageResultExecution timeMemory
168161AlexPop28Triple Jump (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...