Submission #245389

#TimeUsernameProblemLanguageResultExecution timeMemory
245389rama_pangFire (JOI20_ho_t5)C++14
100 / 100
499 ms73372 KiB
// Solution:
//
// Draw a grid, with rows as time and columns as index. For each original S,
// it must for a parallelogram. Each parallelogram can be decomposed into
// triangles. Each triangle can be stored in 2 Dat Structures that support
// range add and range query, where 1 stores diagonals and the other stores
// the vertical aspect. For the diagonal, we can shift query ranges to the
// left, leaving a rectangular one as well. This can be done using a segment
// tree or 2 fenwick trees, each.

#include <bits/stdc++.h>
using namespace std;

class Fenwick {
 private:
  int sz;
  vector<long long> tree;

 public:
  Fenwick() {}
  Fenwick(int sz) : sz(sz) {
    tree.assign(sz, 0);
  }

  void Update(int p, long long x) {
    p += sz / 2;
    for (int i = p; i < sz; i |= i + 1) {
      tree[i] += x;
    }
  }

  long long Query(int p) {
    p += sz / 2;
    long long res = 0;
    for (int i = p + 1; i > 0; i &= i - 1) {
      res += tree[i - 1];
    }
    return res;
  }
};

const int MAXN = 400005;

int N, Q;
int S[MAXN];
int L[MAXN], R[MAXN];

vector<array<int, 3>> query[MAXN];
long long ans[MAXN];

Fenwick start_pref(2 * MAXN);
Fenwick start_const(2 * MAXN);
Fenwick end_pref(2 * MAXN);
Fenwick end_const(2 * MAXN);

vector<array<int, 3>> update[MAXN];

void AddTriangle(int l, int r, int v) {
  if (l > r) return;
  update[0].push_back({l, r, v});
  update[r - l + 1].push_back({l, r, -v});
}

void Update(int t) {
  for (auto u : update[t]) {
    int l, r, v;
    l = u[0], r = u[1], v = u[2];
    start_pref.Update(l, v);
    start_const.Update(l, 1ll * v * (l - 1));
    end_pref.Update(r + 1, -v);
    end_const.Update(r + 1, -1ll * v * r);
  }
}

long long Query(int t, int r) {
  long long start_ = 1ll * (r - t) * start_pref.Query(r - t) - start_const.Query(r - t); // shift to the left
  long long end_ = 1ll * r * end_pref.Query(r) - end_const.Query(r);
  return start_ + end_; 
}

long long Query(int t, int l, int r) {
  return Query(t, r) - Query(t, l - 1);
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);

  cin >> N >> Q;
  for (int i = 1; i <= N; i++) {
    cin >> S[i];
    L[i] = - N - 1;
    R[i] = + N + 1;
  }
  vector<int> st;
  for (int i = 1; i <= N; i++) {
    while (!st.empty() && S[st.back()] <= S[i]) {
      st.pop_back();
    }
    if (!st.empty()) {
      L[i] = st.back();
    }
    st.emplace_back(i);
  }
  st.clear();
  for (int i = N; i >= 1; i--) {
    while (!st.empty() && S[st.back()] < S[i]) {
      st.pop_back();
    }
    if (!st.empty()) {
      R[i] = st.back();
    }
    st.emplace_back(i);
  }
  for (int i = 1; i <= N; i++) {
    AddTriangle(L[i] + 1, R[i] - 1, S[i]);
    AddTriangle(L[i] + 1, i - 1, -S[i]);
    AddTriangle(i + 1, R[i] - 1, -S[i]);
  }
  for (int i = 0; i < Q; i++) {
    int t, l, r;
    cin >> t >> l >> r;
    query[t].push_back({l, r, i});
  }
  for (int t = 0; t <= N; t++) {
    Update(t);
    for (auto &q : query[t]) {
      ans[q[2]] = Query(t, q[0], q[1]);
    }
  }
  for (int i = 0; i < Q; i++) {
    cout << ans[i] << "\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...
#Verdict Execution timeMemoryGrader output
Fetching results...