제출 #1280395

#제출 시각아이디문제언어결과실행 시간메모리
1280395heymynameiskira푸드 코트 (JOI21_foodcourt)C++20
100 / 100
400 ms44388 KiB
#include <bits/stdc++.h> using namespace std; using ll = long long; class Fenwick { private: vector<ll> val; public: Fenwick(int n) : val(n+1, 0) {} // Adds v to index i void add(int i, ll v) { for (++i; i < val.size(); i += i & -i) { val[i] += v; } } // Calculates prefix sum up to index i ll get(int i) { ll res = 0; for (++i; i > 0; i -= i & -i) { res += val[i]; } return res; } ll get(int a, int b) { return get(b) - get(a-1); } }; // Segment tree for range minimum and addition. class SegTree { private: const ll NEUT = 4 * (ll)1e18; vector<ll> seg, tag; int h = 1; void apply(int i, ll v) { seg[i] += v; if (i < h) tag[i] += v; } void push(int i) { if (tag[i] == 0) return; apply(2*i, tag[i]); apply(2*i+1, tag[i]); tag[i] = 0; } ll combine(ll a, ll b) { return min(a, b); } ll recGet(int a, int b, int i, int ia, int ib) { if (ib <= a || b <= ia) return NEUT; if (a <= ia && ib <= b) return seg[i]; push(i); int im = (ia + ib) >> 1; return combine( recGet(a, b, 2*i, ia, im), recGet(a, b, 2*i+1, im, ib)); } void recApply(int a, int b, ll v, int i, int ia, int ib) { if (ib <= a || b <= ia) return; if (a <= ia && ib <= b) apply(i, v); else { push(i); int im = (ia + ib) >> 1; recApply(a, b, v, 2*i, ia, im); recApply(a, b, v, 2*i+1, im, ib); seg[i] = combine(seg[2*i], seg[2*i+1]); } } int recFind(int a, int b, ll v, int i, int ia, int ib) { if (seg[i] > v) return b; if (b <= ia || ib <= a) return b; if (ib == ia + 1) return ia; push(i); int im = (ia + ib) >> 1; int off = recFind(a, b, v, 2*i, ia, im); if (off < b) return off; else return recFind(a, b, v, 2*i+1, im, ib); } public: SegTree(int n) { while(h < n) h *= 2; seg.resize(2*h, 0); tag.resize(h, 0); } ll rangeMin(int a, int b) { return recGet(a, b+1, 1, 0, h); } void rangeAdd(int a, int b, ll v) { recApply(a, b+1, v, 1, 0, h); } int findNext(int a, int b, ll v) { return recFind(a, b+1, v, 1, 0, h); } }; struct SegTreeBeats { private: struct Node { ll add; // pending range add to push to children ll cap; // node value capped by ceilings from ancestors Node(): add(0), cap(0) {} }; const ll INF = 4 * (ll)1e18; int n; // number of leaves (power of two not required) std::vector<Node> st; // 4*n is fine in this style // same semantics as original: // "add a, then clamp by c" on the current node inline void apply(int head, ll a, ll c) { st[head].cap = std::min(st[head].cap + a, c); st[head].add += a; // add is only for children (will be used in push) } // push parent's (add, cap) to children, then clear parent tags inline void push(int head) { // left child apply(head << 1, st[head].add, st[head].cap); // right child apply(head << 1 | 1, st[head].add, st[head].cap); // clear tags on this node st[head].add = 0; st[head].cap = INF; // after pushing, the parent's own ceiling becomes "no ceiling" } // range add (pure add because we pass c = +INF at covered nodes) void recAdd(int head, int l, int r, int ql, int qr, ll v) { if (r <= ql || qr <= l) return; if (ql <= l && r <= qr) { apply(head, v, INF); // add only (no cap) return; } push(head); int mid = (l + r) >> 1; recAdd(head << 1, l, mid, ql, qr, v); recAdd(head << 1 | 1, mid, r, ql, qr, v); // no pull step: the structure's query returns st[head].cap directly } // query max over [ql, qr) — identical to the original recMax behavior ll recMax(int head, int l, int r, int ql, int qr) { if (r <= ql || qr <= l) return -INF; if (ql <= l && r <= qr) return st[head].cap; push(head); int mid = (l + r) >> 1; return std::max(recMax(head << 1, l, mid, ql, qr), recMax(head << 1 | 1, mid, r, ql, qr)); } public: // n = logical size (0..n-1). We allocate 4*n nodes like your usual style. SegTreeBeats(int n): n(n) { st.assign(4 * n + 5, Node()); // all nodes start with add=0, cap=0 (same as original) } // add v to [a, b] inclusive (original code uses [a, b+1) under the hood) void rangeAdd(int a, int b, ll v) { recAdd(1, 0, n, a, b + 1, v); // impose "global ceiling 0" at the root (exactly like the original apply(1,0,0)) apply(1, 0, 0); } // point get at i (returns min(A[i], current_root_ceiling)) ll get(int i) { return recMax(1, 0, n, i, i + 1); } }; const string name = "test"; int main() { if (fopen((name + ".inp").c_str(), "r")) { freopen((name + ".inp").c_str(), "r", stdin); freopen((name + ".out").c_str(), "w", stdout); } ios_base::sync_with_stdio(false); cin.tie(0); int n, m, q; cin >> n >> m >> q; SegTreeBeats cur(n); Fenwick tot(n+1); vector<int> res; vector<vector<pair<ll, int>>> qs(n); vector<array<ll, 5>> ops(q); for (int qi = 0; qi < q; ++qi) { cin >> ops[qi][0]; ll a, b; cin >> a >> b; --a; --b; ops[qi][1] = a; ops[qi][2] = b; if (ops[qi][0] == 1) { ll c, k; cin >> c >> k; ops[qi][3] = c; ops[qi][4] = k; cur.rangeAdd(a, b, -k); tot.add(a, k); tot.add(b+1, -k); } else if (ops[qi][0] == 2) { ll k; cin >> k; ops[qi][3] = k; cur.rangeAdd(a, b, k); } else if (ops[qi][0] == 3) { ++b; ll v = -cur.get(a); int ind = res.size(); res.emplace_back(0); if (v >= b) qs[a].emplace_back(tot.get(a) - (v - b), ind); } } const ll INF = 1e18; SegTree groups(n); vector<int> inds(n, 0); for (int i = 0; i < n; ++i) { if (qs[i].empty()) { groups.rangeAdd(i, i, INF); } else { sort(qs[i].begin(), qs[i].end()); groups.rangeAdd(i, i, qs[i][0].first); } } for (int qi = 0; qi < q; ++qi) { int t = ops[qi][0]; if (t == 1) { ll a = ops[qi][1]; ll b = ops[qi][2]; ll c = ops[qi][3]; ll k = ops[qi][4]; groups.rangeAdd(a, b, -k); while(true) { int j = groups.findNext(0, n-1, 0); if (j == n) break; res[qs[j][inds[j]].second] = c; ++inds[j]; if (inds[j] >= qs[j].size()) { groups.rangeAdd(j, j, INF); } else { groups.rangeAdd(j, j, qs[j][inds[j]].first - qs[j][inds[j] - 1].first); } } } } for (auto c : res) cout << c << '\n'; }

컴파일 시 표준 에러 (stderr) 메시지

foodcourt.cpp: In function 'int main()':
foodcourt.cpp:170:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  170 |         freopen((name + ".inp").c_str(), "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
foodcourt.cpp:171:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  171 |         freopen((name + ".out").c_str(), "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...