Submission #579057

#TimeUsernameProblemLanguageResultExecution timeMemory
579057KoD사탕 분배 (IOI21_candies)C++17
11 / 100
5051 ms8936 KiB
#include "candies.h" #include <bits/stdc++.h> using std::array; using std::pair; using std::tuple; using std::vector; using ll = long long; template <class T> constexpr T infty = std::numeric_limits<T>::max() / 2; template <class F> struct fixed : private F { explicit fixed(F&& f) : F(std::forward<F>(f)) {} template <class... Args> decltype(auto) operator()(Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); } }; template <class T> class fenwick_tree { vector<T> data; public: explicit fenwick_tree(const int n) : data(n + 1) {} void add(int i, const T& x) { i += 1; while (i < (int)data.size()) { data[i] += x; i += i & -i; } } T pref(int i) const { T ret = 0; while (i > 0) { ret += data[i]; i -= i & -i; } return ret; } T fold(const int l, const int r) const { return pref(r) - pref(l); } }; struct func { int lb, ub, add; int eval(const int x) { return std::clamp(x, lb, ub) + add; } }; constexpr func unit = {-infty<int>, infty<int>, 0}; func composition(const func& f, const func& g) { auto [l1, r1, a1] = f; auto [l2, r2, a2] = g; l2 -= a1; r2 -= a1; a2 += a1; if (r1 <= l2) return {l2, l2, a2}; if (r2 <= l1) return {r2, r2, a2}; return {std::max(l1, l2), std::min(r1, r2), a2}; } class segtree { int size, logn; vector<func> data; void apply(const int k, const func& f) { data[k] = composition(data[k], f); } void flush(const int k) { apply(2 * k, data[k]); apply(2 * k + 1, data[k]); data[k] = unit; } void push(int k) { const int z = __builtin_ctz(k); for (int d = logn; d > z; --d) { flush(k >> d); } } public: explicit segtree(const int n) { logn = 0; while ((1 << logn) < n) logn += 1; size = 1 << logn; data.resize(2 * size, unit); } void apply(int l, int r, const func& f) { l += size; r += size; push(l); push(r); while (l < r) { if (l & 1) apply(l++, f); if (r & 1) apply(--r, f); l >>= 1; r >>= 1; } } func get(int k) { k += size; for (int d = logn; d > 0; --d) { flush(k >> d); } return data[k]; } }; vector<int> distribute_candies(vector<int> C, vector<int> L, vector<int> R, vector<int> V) { const int N = (int)C.size(); const int Q = (int)L.size(); for (auto& x : R) x += 1; if (N <= 2000 and Q <= 2000) { vector<int> X(N); for (int q = 0; q < Q; ++q) { for (int i = L[q]; i < R[q]; ++i) { X[i] = std::clamp(X[i] + V[q], 0, C[i]); } } return X; } if (*std::min_element(V.begin(), V.end()) > 0) { fenwick_tree<ll> fen(N); for (int q = 0; q < Q; ++q) { fen.add(L[q], V[q]); fen.add(R[q], -V[q]); } vector<int> X(N); for (int i = 0; i < N; ++i) { const ll tmp = fen.pref(i + 1); X[i] = tmp >= C[i] ? C[i] : tmp; } return X; } if (std::count(C.begin(), C.end(), C[0]) == N) { segtree seg(N); for (int q = 0; q < Q; ++q) { seg.apply(L[q], R[q], {-V[q], C[0] - V[q], V[q]}); } vector<int> X(N); for (int i = 0; i < N; ++i) { X[i] = seg.get(i).eval(0); } return X; } vector<ll> sum(Q + 1); std::map<int, pair<int, int>> last; const auto calc = [&](const int i, const int t) { const auto [s, x] = last.upper_bound(i)->second; return (x == 0 ? 0 : C[i]) + (sum[t] - sum[s]); }; last[0] = {N, 0}; for (int q = 0; q < Q; ++q) { sum[q + 1] = sum[q] + V[q]; int ng = -1, ok = N; while (std::abs(ng - ok) > 1) { const int md = (ok + ng) / 2; const int val = calc(md, q + 1); if (val < 0 or C[md] < val) { ng = md; } else { ok = md; } } while (last.begin() -> first < ok) { last.erase(last.begin()); } last[ok] = {q + 1, V[q] < 0}; } vector<int> X(N); for (int i = 0; i < N; ++i) { X[i] = calc(i, Q); } return X; }
#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...