제출 #1362212

#제출 시각아이디문제언어결과실행 시간메모리
1362212avighnaLegendary Dango Eater (JOI26_dango)C++20
100 / 100
2266 ms1000768 KiB
#include <bits/stdc++.h>

using namespace std;

const int inf = 1e9;

class sparse_segment_tree {
  struct node {
    node *l, *r;
    int x, lazy;
    node() : x(inf), lazy(-1), l(nullptr), r(nullptr) {}
    ~node() {
      delete l;
      delete r;
    }
  };
  node *t;
  int64_t n;

  void push(node *t) {
    t->l = t->l ? t->l : new node();
    t->r = t->r ? t->r : new node();
    if (t->lazy != -1) {
      t->x = t->lazy;
      t->l->lazy = t->lazy;
      t->r->lazy = t->lazy;
      t->lazy = -1;
    }
  }

  void pull(node *t) {
    t->x = min(t->l->x, t->r->x);
  }

  void set(node *t, int64_t tl, int64_t tr, int64_t l, int64_t r, int x) {
    push(t);
    if (tr < l || r < tl) return;
    if (l <= tl && tr <= r) {
      t->lazy = x;
      push(t);
      return;
    }
    int64_t tm = midpoint(tl, tr);
    set(t->l, tl, tm, l, r, x);
    set(t->r, tm + 1, tr, l, r, x);
    pull(t);
  }

  int at(node *t, int64_t tl, int64_t tr, int64_t i) {
    push(t);
    if (tr < i || i < tl) return inf;
    if (i <= tl && tr <= i) return t->x;
    int64_t tm = midpoint(tl, tr);
    return min(at(t->l, tl, tm, i), at(t->r, tm + 1, tr, i));
  }

public:
  sparse_segment_tree(int64_t n) : n(n), t(new node()) {}
  ~sparse_segment_tree() { delete t; }

  void set(int64_t l, int64_t r, int x) {
    if (l <= r) {
      set(t, 0, n - 1, l, r, x);
    } else {
      set(t, 0, n - 1, l, n - 1, x);
      set(t, 0, n - 1, 0, r, x);
    }
  }
  int at(int64_t i) { return at(t, 0, n - 1, i); }
};

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);

  int n, q;
  int64_t k;
  cin >> n >> q >> k;
  vector<int64_t> a(n);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
    if (i & 1) {
      a[i] = -a[i];
    }
  }

  vector<int64_t> pa(n + 1);
  partial_sum(a.begin(), a.end(), pa.begin() + 1);
  const int w = bit_width(unsigned(n));
  vector lift(w, vector<int>(n + 1));
  vector table(w, vector<int64_t>(n + 1));
  auto modk = [&](int64_t x) { return ((x % k) + k) % k; };
  sparse_segment_tree st(k);
  for (int i = n - 1, small = n; i >= 0; --i) {
    if (a[i] < 0) {
      int64_t lo = modk(-pa[i]), hi = modk(-pa[i] - a[i] - 1);
      st.set(lo, hi, i);
    }
    if (a[i] <= -k) {
      small = i;
    }
    int j = min(small, st.at(modk(-pa[i])));
    lift[0][i] = min(n, j + 1);
    table[0][i] = (pa[j] - pa[i]) / k;
  }
  lift[0][n] = n;

  for (int bt = 1; bt < w; ++bt) {
    for (int i = 0; i <= n; ++i) {
      lift[bt][i] = lift[bt - 1][lift[bt - 1][i]];
      table[bt][i] = table[bt - 1][i] + table[bt - 1][lift[bt - 1][i]];
    }
  }

  auto query = [&](int l, int r) {
    r++;
    int64_t ans = 0;
    for (int bt = w - 1; bt >= 0; --bt) {
      if (lift[bt][l] <= r) {
        ans += table[bt][l];
        l = lift[bt][l];
      }
    }
    return ans + (pa[r] - pa[l]) / k;
  };

  while (q--) {
    int l, r;
    cin >> l >> r;
    --l, --r;
    cout << query(l, r) << '\n';
  }
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…