Submission #1096927

#TimeUsernameProblemLanguageResultExecution timeMemory
1096927andrei_iorgulescuThe short shank; Redemption (BOI21_prison)C++14
70 / 100
2069 ms70444 KiB
#include <bits/stdc++.h> using namespace std; using ld = long double; ld eps = 0.000001d; int n, d, t, v[2000005], k[2000005]; int bad; struct copacel { ld val = 0; int cate = 0; }; copacel dp[2000005]; int sz[2000005]; vector<int> f[2000005]; ld c; void dfs(int nod) { for (auto fiu : f[nod]) dfs(fiu); copacel var1, var2; var1.cate = 1; var1.val = c; for (auto fiu : f[nod]) { if (dp[fiu].val < sz[fiu]) { var1.cate += dp[fiu].cate; var1.val += dp[fiu].val; } else var1.val += sz[fiu]; } if (f[nod].empty()) { dp[nod] = var1; return; } var2.val = var2.cate = 0; ld mindif = 1e9; for (auto fiu : f[nod]) mindif = min(mindif, dp[fiu].val - min(dp[fiu].val, (ld)sz[fiu])); bool tkn = false; for (auto fiu : f[nod]) { if (!tkn and dp[fiu].val - min(dp[fiu].val, (ld)sz[fiu]) == mindif) { tkn = true; var2.cate += dp[fiu].cate; var2.val += dp[fiu].val; } else { if (dp[fiu].val < sz[fiu]) { var2.cate += dp[fiu].cate; var2.val += dp[fiu].val; } else var2.val += sz[fiu]; } } if (var1.val < var2.val) assert(false); if (var1.val <= var2.val) dp[nod] = var1; else dp[nod] = var2; } void solve(ld cost) { c = cost; for (int i = 1; i <= n; i++) dp[i].val = dp[i].cate = 0; dfs(1); } void ufuf(int nod) { sz[nod] = 1; for (auto fiu : f[nod]) { ufuf(fiu); sz[nod] += sz[fiu]; } } void build_tree() { vector<pair<int,int>> ranges; for (int i = 1; i <= n; i++) { int j; for (j = i; j >= 1; j--) { if (v[j] + i - j <= t) break; } if (j == i) bad++; else if (j != 0) ranges.push_back({j, i - 1}); } if (ranges.empty()) { n = 0; return; } ranges.push_back({1, n}); /*for (auto it1 : ranges) { for (auto it2 : ranges) { bool bb = false; if (it1.second < it2.first) bb = true; if (it2.second < it1.first) bb = true; if (it1.first <= it2.first and it2.second <= it1.second) bb = true; if (it2.first <= it1.first and it1.second <= it2.second) bb = true; if (bb == false) assert(false); } }*/ sort(ranges.begin(), ranges.end(), [](pair<int,int> A, pair<int,int> B){ if (A.first != B.first) return A.first < B.first; return A.second > B.second; }); n = ranges.size(); stack<int> stk; stk.push(1); for (int i = 1; i < n; i++) { while (ranges[stk.top() - 1].second < ranges[i].first) stk.pop(); f[stk.top()].push_back(i + 1); stk.push(i + 1); } ufuf(1); } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> n >> d >> t; for (int i = 1; i <= n; i++) cin >> v[i]; for (int i = 1; i <= n; i++) k[i] = v[i] - i; build_tree(); if (n - 1 <= d) { cout << bad; return 0; } ld st = n, pas = (ld)(1 << 20); while (pas >= eps) { if (st - pas >= 1) { solve(st - pas); if (dp[1].cate <= d) st -= pas; } pas /= 2.0d; } solve(st); ld ans = dp[1].val - (ld)d * st; int aa = ans; if (ans - (ld)aa >= 0.5d) aa++; cout << aa + bad; return 0; } /** yeah so aliens pe fata pentru i, imi fac un interval de tipul: "daca pun aici un gate nu o sa se mai revolte i" in fine, astea au structura de arbore din fericire, deci dupa ce imi fac arborele si aliens, e doar un dp[nod][0/1] **/
#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...