제출 #1340865

#제출 시각아이디문제언어결과실행 시간메모리
1340865avighna푸드 코트 (JOI21_foodcourt)C++20
100 / 100
632 ms107080 KiB
#include <bits/stdc++.h>

using namespace std;

template <typename T>
struct op {
  T s, m;
  op() : s(0), m(numeric_limits<T>::min() >> 2) {}
  op(T s, T m) : s(s), m(m) {}
  op operator+(const op &other) {
    return op{s + other.s, max(m + other.s, other.m)};
  }
};

template <typename T, typename F>
class lazy_segment_tree {
private:
  int n;
  vector<T> seg;
  vector<F> lazy;
  static constexpr bool is_op = std::same_as<F, op<T>>;

public:
  lazy_segment_tree(int n) : n(n), seg(4 * n), lazy(8 * n, F{}) {}

  void push(int v, int tl, int tr) {
    if constexpr (is_op) {
      seg[v] = max(seg[v] + lazy[v].s, lazy[v].m);
    } else {
      seg[v] = seg[v] + lazy[v];
    }
    lazy[2 * v] = lazy[2 * v] + lazy[v];
    lazy[2 * v + 1] = lazy[2 * v + 1] + lazy[v];
    if constexpr (is_op) {
      lazy[v] = F{};
    } else {
      lazy[v] = 0;
    }
  }

  void update(int v, int tl, int tr, int l, int r, F oper) {
    push(v, tl, tr);
    if (tr < l || r < tl) {
      return;
    }
    if (l <= tl && tr <= r) {
      lazy[v] = lazy[v] + oper;
      push(v, tl, tr);
      return;
    }
    int tm = (tl + tr) / 2;
    update(2 * v, tl, tm, l, r, oper);
    update(2 * v + 1, tm + 1, tr, l, r, oper);
    seg[v] = max(seg[2 * v], seg[2 * v + 1]);
  }
  void update(int l, int r, F oper) { update(1, 0, n - 1, l, r, oper); }
  void chmax(int l, int r)
    requires std::same_as<F, op<T>>
  { update(1, 0, n - 1, l, r, {0, 0}); }
  void add(int l, int r, T del)
    requires std::same_as<F, op<T>>
  { update(1, 0, n - 1, l, r, {del, numeric_limits<T>::min() >> 2}); }

  T query(int v, int tl, int tr, int idx) {
    push(v, tl, tr);
    if (tr < idx || idx < tl) {
      return numeric_limits<T>::min() >> 2;
    }
    if (idx <= tl && tr <= idx) {
      return seg[v];
    }
    int tm = (tl + tr) / 2;
    return max(query(2 * v, tl, tm, idx), query(2 * v + 1, tm + 1, tr, idx));
  }
  T query(int idx) { return query(1, 0, n - 1, idx); }

  template <typename Fn>
  int min_right(int v, int tl, int tr, const Fn &f) {
    push(v, tl, tr);
    if (!f(seg[v])) {
      return -1;
    }
    if (tl == tr) {
      return tl;
    }
    int tm = (tl + tr) / 2;
    int l = min_right(2 * v, tl, tm, f);
    if (l != -1) {
      return l;
    }
    return min_right(2 * v + 1, tm + 1, tr, f);
  }
  template <typename Fn>
  int min_right(const Fn &f) { return min_right(1, 0, n - 1, f); }
};

struct query {
  int t, l, r, a;
  int64_t c, k, b;
};

struct question {
  int i;
  int64_t b;
  int idx;
  bool operator<(const question &r) { return b < r.b; }
};

const int64_t inf = numeric_limits<int64_t>::max() >> 2;

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  int n, m, q;
  cin >> n >> m >> q;

  vector<query> queries(q);
  for (int i = 0; i < q; ++i) {
    auto &[t, l, r, a, c, k, b] = queries[i];
    cin >> t;
    if (t == 1) {
      cin >> l >> r >> c >> k;
      --l, --r;
    } else if (t == 2) {
      cin >> l >> r >> k;
      --l, --r;
    } else {
      cin >> a >> b;
      --a;
    }
  }

  lazy_segment_tree<int64_t, int64_t> st_tot(n);
  lazy_segment_tree<int64_t, op<int64_t>> st_cur(n);
  vector<vector<question>> questions(n);
  int cnt = 0;
  for (int i = 0; i < q; ++i) {
    auto &[t, l, r, a, c, k, b] = queries[i];
    if (t == 1) {
      st_tot.update(l, r, k);
      st_cur.add(l, r, k);
    } else if (t == 2) {
      st_cur.add(l, r, -k);
      st_cur.chmax(l, r);
    } else {
      questions[a].push_back({cnt++, b + st_tot.query(a) - st_cur.query(a), i});
    }
  }

  for (auto &i : questions) {
    sort(i.rbegin(), i.rend());
  }
  lazy_segment_tree<int64_t, int64_t> st(n);
  for (int i = 0; i < n; ++i) {
    st.update(i, i, -(questions[i].empty() ? inf : questions[i].back().b));
  }

  vector<int> ans(cnt);
  for (int i = 0; i < q; ++i) {
    auto &[t, l, r, a, c, k, b] = queries[i];
    if (t == 1) {
      st.update(l, r, k);
      auto f = [&](int64_t x) { return x >= 0; };
      for (int idx = st.min_right(f); idx != -1; idx = st.min_right(f)) {
        int sz = questions[idx].size();
        if (questions[idx][sz - 1].idx > i) {
          ans[questions[idx][sz - 1].i] = c;
        }
        if (sz >= 2) {
          int64_t del = questions[idx][sz - 2].b - questions[idx][sz - 1].b;
          questions[idx].pop_back();
          st.update(idx, idx, -del);
        } else {
          st.update(idx, idx, -inf);
        }
      }
    }
  }

  for (int &i : ans) {
    cout << i << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...