Submission #387313

#TimeUsernameProblemLanguageResultExecution timeMemory
387313rama_pangFood Court (JOI21_foodcourt)C++17
100 / 100
942 ms47596 KiB
#include <bits/stdc++.h> using namespace std; using lint = long long; const lint inf = 1e18; // Build Segment Tree over queries // We need to simulate operations fast // Can be done with matrix-like multiplication // O(N + Q log Q). // // Matrix Multiplication: // [a, b] [e] = [min(a + e, b + f)] // [c, d] [f] = [min(c + e, d + f)] // // Identity: // [0, inf] [head] // [inf, 0] [tail] // // Push Back // [0, inf] [head] // [inf, K] [tail] // // Pop Front // [K, 0] [head] // [inf, 0] [tail] struct Matrix { array<array<lint, 2>, 2> M; Matrix(lint K = 0) { if (K == 0) { // Identity M[0] = {0, inf}; M[1] = {inf, 0}; } else if (K > 0) { // Push Back M[0] = {0, inf}; M[1] = {inf, K}; } else if (K < 0) { // Pop Front M[0] = {-K, 0}; M[1] = {inf, 0}; } } friend Matrix operator*(const Matrix &a, const Matrix &b) { Matrix c; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { c.M[i][j] = min(a.M[i][0] + b.M[0][j], a.M[i][1] + b.M[1][j]); } } return c; } }; class SegTree { public: int sz; vector<Matrix> tree; SegTree(int n) { sz = 1; while (sz < n) sz *= 2; tree.assign(2 * sz, Matrix(0)); } void Modify(int p, int K) { tree[p += sz] = Matrix(K); for (p /= 2; p > 0; p /= 2) { tree[p] = tree[p * 2 + 1] * tree[p * 2]; } } pair<lint, lint> Query(int l, int r) { // (head, tail) Matrix L(0), R(0); for (l += sz, r += sz + 1; l < r; l /= 2, r /= 2) { if (l & 1) L = tree[l++] * L; if (r & 1) R = R * tree[--r]; } L = R * L; return pair(min(L.M[0][0], L.M[0][1]), min(L.M[1][0], L.M[1][1])); } }; int main() { ios::sync_with_stdio(0); cin.tie(0); int N, M, Q; cin >> N >> M >> Q; vector<int> ans(Q + 1, -1); vector<int> color(Q + 1, -1); vector<vector<array<lint, 3>>> Query(N + 1); for (int q = 1; q <= Q; q++) { int T; cin >> T; if (T == 1) { lint L, R, K; cin >> L >> R >> color[q] >> K; Query[L - 1].push_back({0, q, K}); Query[R].push_back({0, q, 0}); } else if (T == 2) { lint L, R, K; cin >> L >> R >> K; Query[L - 1].push_back({0, q, -K}); Query[R].push_back({0, q, 0}); } else if (T == 3) { lint A, B; cin >> A >> B; Query[A - 1].push_back({1, q, B}); } } SegTree seg(Q + 1); for (int S = 0; S < N; S++) { // Current shop for (auto [t, q, k] : Query[S]) { if (t == 0) { seg.Modify(q, k); } else if (t == 1) { auto [head, tail] = seg.Query(0, q); lint ans_pos = head + k - 1; if (ans_pos >= tail) { ans[q] = 0; } else { int lo = 0, hi = q; while (lo < hi) { int md = (lo + hi) / 2; if (ans_pos < seg.Query(0, md).second) { hi = md; } else { lo = md + 1; } } assert(color[lo] != -1); ans[q] = color[lo]; } } } } for (int q = 1; q <= Q; q++) { if (ans[q] != -1) { cout << ans[q] << '\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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...