Solution -「JOISC 2021」フードコート

cirnovsky /

不是很懂啊,为什么写 ji segtree 啊。

具体做法楼上老哥已经写了,我只做一个补充,因为是单点查询,所以只需要将 segtree 写成一棵完全意义的 leafy tree 即可(就是不用写 pushup 的意思)。

大概意思就是,这个 segment tree beats。首先这里没有必要真的写一个出来,因为注意到是单点询问。但是这里的线段树有一些不同于传统的线段树,尽管传统线段树也是一棵 leafy tree,但是这里树的非叶结点上是没有信息需要维护的。可以把 lazy propagation 和你维护的幺半群放到一个数组来写。

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

const i64 inf = 1e9;
int N, M, Q, sz, h, ans[250100];
i64 dat[250100];
struct rec {
  i64 p, q;
} lz[524388];
struct req {
  i64 a, b, c, d;
} q[250100];
void add(int x, i64 v) {
  for (; x <= N + 1; x += x & -x) dat[x] += v;
}
void add(int l, int r, i64 v) { add(l, v), add(r + 1, -v); }
i64 sum(i64 x) {
  i64 res = 0;
  for (; x; x -= x & -x) res += dat[x];
  return res;
}
rec composition(rec f, rec v) { return {v.p + f.p, max(v.q + f.p, f.q)}; }
void propagate(int x, rec f) { lz[x] = composition(f, lz[x]); }
void push(int x) {
  propagate(x * 2, lz[x]), propagate(x * 2 + 1, lz[x]), lz[x] = {0, -inf};
}
void add(int l, int r, rec f) {
  assert(0 <= l && l <= r && r <= N);
  if (l == r) return;
  l += sz, r += sz;
  for (int i = h; i >= 1; --i) {
    if (((l >> i) << i) != l) push(l >> i);
    if (((r >> i) << i) != r) push((r - 1) >> i);
  }
  for (; l < r; l >>= 1, r >>= 1) {
    if (l & 1) propagate(l++, f);
    if (r & 1) propagate(--r, f);
  }
}
i64 get(i64 x) {
  assert(0 <= x && x < N);
  for (i64 i = h; i >= 1; --i) push((x + sz) >> i);
  return max(lz[x + sz].p, lz[x + sz].q);
}

void dac(int l, int r, const vector<int>& id) {
  if (id.empty()) return;
  if (l == r) {
    for (auto&& it : id) ans[it] = l;
    return;
  }
  int mid = (l + r) / 2;
  for (int i = l; i <= mid; ++i)
    if (q[i].c && q[i].d) add(q[i].a, q[i].b, q[i].d);
  vector<int> ql, qr;
  for (auto&& it : id) (sum(q[it].a) >= q[it].b ? ql : qr).emplace_back(it);
  dac(mid + 1, r, qr);
  for (int i = l; i <= mid; ++i)
    if (q[i].c && q[i].d) add(q[i].a, q[i].b, -q[i].d);
  dac(l, mid, ql);
}

signed main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> N >> M >> Q;
  h = ceil(log2(N)), sz = 1 << h;
  for (int i = 0; i <= N; ++i) lz[i + sz] = {0, -inf};
  vector<int> is;
  for (i64 o, l, r, c, k, i = 1; i <= Q; ++i) {
    cin >> o >> l >> r, c = k = 0;
    if (o == 1)
      cin >> c >> k, add(l, r, k), add(l - 1, r, {k, 0});
    else if (o == 2)
      cin >> k, add(l - 1, r, {-k, 0});
    else
      r += sum(l) - get(l - 1), is.emplace_back(i);
    q[i] = {l, r, c, k};
  }
  memset(dat, 0, sizeof(dat)), dac(1, Q + 1, is);
  for (int i = 1; i <= Q; ++i)
    if (q[i].c == 0 && q[i].d == 0)
      cout << q[ans[i] > i ? 0 : ans[i]].c << "\n";
  return 0;
}