Submission #589925

#TimeUsernameProblemLanguageResultExecution timeMemory
589925Drew_Distributing Candies (IOI21_candies)C++17
0 / 100
5087 ms50612 KiB
#include "candies.h" #include <bits/stdc++.h> using namespace std; #define pb push_back #define f1 first #define s2 second using ii = pair<int, int>; using ll = long long; const int MAX = 2e5 + 69; const ll inf = (ll)1e18 + 69; struct Segtree { struct Node { ll sum; ll mx, pmx, smx; // maximum, prefix maximum, suffix maximum ll mn, pmn, smn; // minimum, prefix minimum, suffix minimum Node() : sum(0), mx(-inf), pmx(mx), smx(mx), mn(inf), pmn(mn), smn(mn) {} Node(ll val) : sum(val), mx(val), pmx(mx), smx(mx), mn(val), pmn(mn), smn(mn) {} friend Node operator+ (const Node &lhs, const Node &rhs) { Node res; res.sum = lhs.sum + rhs.sum; res.pmx = max(lhs.pmx, lhs.sum + rhs.pmx); res.smx = max(rhs.sum + lhs.smx, rhs.smx); res.mx = max({lhs.mx, rhs.mx, lhs.smx + rhs.pmx}); res.pmn = min(lhs.pmn, lhs.sum + rhs.pmn); res.smn = min(rhs.sum + lhs.smn, rhs.smn); res.mn = min({lhs.mn, rhs.mn, lhs.smn + rhs.pmn}); return res; } }; int n; Node st[1 << 19]; Segtree() {} Segtree(int n_) : n(n_) {} inline void modify(int p, ll val) { const auto modify_ = [&](const auto &self, int node, int l, int r) -> void { if (l > p || r < p) return; if (p <= l && r <= p) { if (val == 0) st[node] = Node(); else st[node] = Node(val); return; } int mid = (l + r) >> 1; self(self, node << 1, l, mid); self(self, node << 1 | 1, mid+1, r); st[node] = st[node << 1] + st[node << 1 | 1]; }; modify_(modify_, 1, 0, n-1); } // find the rightmost subarray sum which is >= val inline ii getmx(ll val) { if (st[1].mx < val) return {-1, -1}; Node sfx = Node(), pfx = Node(); const auto getL = [&](const auto &self, int node, int l, int r) -> int { if (l == r) return l; int mid = (l + r) >> 1; Node tmp = st[node << 1 | 1] + sfx; if (tmp.mx >= val) return self(self, node << 1 | 1, mid+1, r); sfx = tmp; return self(self, node << 1, l, mid); }; const auto getR = [&](const auto &self, int node, int l, int r, int L) -> int { int mid = (l + r) >> 1; if (r < L) return -1; if (l < L) { int ret = self(self, node << 1, l, mid, L); if (ret != -1) return ret; return self(self, node << 1 | 1, mid+1, r, L); } Node tmp = pfx + st[node]; if (tmp.mx < val) { pfx = tmp; return -1; } if (l == r) return l; tmp = pfx + st[node << 1]; if (tmp.mx >= val) return self(self, node << 1, l, mid, L); else { pfx = tmp; return self(self, node << 1 | 1, mid+1, r, L); } }; int L = getL(getL, 1, 0, n-1); int R = getR(getR, 1, 0, n-1, L); return {L, R}; } // find the rightmost subarray sum which is <= val inline ii getmn(ll val) { if (st[1].mn > val) return {-1, -1}; Node sfx = Node(), pfx = Node(); const auto getL = [&](const auto &self, int node, int l, int r) -> int { if (l == r) return l; int mid = (l + r) >> 1; Node tmp = st[node << 1 | 1] + sfx; if (tmp.mn <= val) return self(self, node << 1 | 1, mid+1, r); sfx = tmp; return self(self, node << 1, l, mid); }; const auto getR = [&](const auto &self, int node, int l, int r, int L) -> int { int mid = (l + r) >> 1; if (r < L) return -1; if (l < L) { int ret = self(self, node << 1, l, mid, L); if (ret != -1) return ret; return self(self, node << 1 | 1, mid+1, r, L); } Node tmp = pfx + st[node]; if (tmp.mn > val) { pfx = tmp; return -1; } if (l == r) return l; tmp = pfx + st[node << 1]; if (tmp.mn <= val) return self(self, node << 1, l, mid, L); else { pfx = tmp; return self(self, node << 1 | 1, mid+1, r, L); } }; int L = getL(getL, 1, 0, n-1); int R = getR(getR, 1, 0, n-1, L); return {L, R}; } inline ll query(int p, int q) // ask for sum { const auto query_ = [&](const auto &self, int node, int l, int r) -> ll { if (l > q || r < p) return 0; if (p <= l && r <= q) return st[node].sum; int mid = (l + r) >> 1; return self(self, node << 1, l, mid) + self(self, node << 1 | 1, mid+1, r); }; return query_(query_, 1, 0, n-1); } }; vector<int> distribute_candies(vector<int> C, vector<int> L, vector<int> R, vector<int> val) { int N = (int)C.size(), Q = (int)L.size(); vector<int> id = { 0 }; for (int i = 1; i < Q; ++i) { if ((val[i] > 0) == (val[i-1] > 0)) id.pb(id.back()); else id.pb(id.back() + 1); } vector<array<int, 4>> vec; for (int i = 0; i < Q; ++i) vec.pb({L[i], R[i], val[i], id[i]}); sort(vec.begin(), vec.end()); int sz = (int)id.size(); vector<ll> cur(sz, 0); Segtree st = Segtree(sz); vector<int> res(N); priority_queue<array<int, 3>> pq; for (int i = 0, j = 0; i < N; ++i) { while (j < Q && i >= vec[j][0]) { cur[vec[j][3]] += vec[j][2]; st.modify(vec[j][3], cur[vec[j][3]]); pq.push({-vec[j][1], vec[j][2], vec[j][3]}); ++j; } while (!pq.empty() && i > -pq.top()[0]) { cur[pq.top()[2]] -= pq.top()[1]; st.modify(pq.top()[2], cur[pq.top()[2]]); pq.pop(); } cerr << "st: "; for (int x = 0; x < sz; ++x) cerr << st.query(x, x) << " \n"[x == sz-1]; // exit(0); auto [l, r] = st.getmx(C[i]); if (l == -1) { auto [p, q] = st.getmn(0); res[i] = (int)st.query(q+1, sz-1); } else { auto [p, q] = st.getmn(-C[i]); if (r < p) res[i] = (int)st.query(q+1, sz-1); else { auto [a, b] = st.getmx(0); if (q < a) res[i] = C[i] + (int)st.query(b+1, sz-1); else res[i] = C[i] + (int)st.query(r+1, sz-1); } } } return res; } // int main() { // int n; // assert(1 == scanf("%d", &n)); // std::vector<int> c(n); // for(int i = 0; i < n; ++i) { // assert(scanf("%d", &c[i]) == 1); // } // int q; // assert(1 == scanf("%d", &q)); // std::vector<int> l(q), r(q), v(q); // for(int i = 0; i < q; ++i) { // assert(scanf("%d %d %d", &l[i], &r[i], &v[i]) == 3); // } // std::vector<int> ans = distribute_candies(c, l, r, v); // for(int i = 0; i < n; ++i) { // if (i > 0) { // printf(" "); // } // printf("%d", ans[i]); // } // printf("\n"); // fclose(stdout); // 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...