Skip to content

Commit 6480035

Browse files
committed
BOI 21 Prison
1 parent faa6df0 commit 6480035

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

Baltic/Baltic 21-prison.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Baltic 2021 The short shank; Redemption
3+
- Call prisoners with t[i] <= T "active" and others "passive"
4+
- We basically want to maximize the number of passive prisoners
5+
that don't protest
6+
- Consider a forest where:
7+
- The nodes are the passive prisoners
8+
- The parent of node i is the first prisoner to the right of
9+
i that won't rebel if there's a mattress to the left of i
10+
- We can find this forest by sweeping through the prisoners and
11+
using a stack
12+
- We know that par[i] > j iff there exists some k in [i, j)
13+
where k + T - t[k] >= j, and suffix maximums are monotonic
14+
- Next, we can just do the following D times:
15+
- Take the longest path in the forest from a root to a leaf
16+
- Subtract that path's length from the answer
17+
- Remove all nodes on that path from the graph
18+
- Since we traverse each node at most once, this runs in
19+
O(N log N) time (if we use a priority queue to find the
20+
longest path efficiently)
21+
*/
22+
23+
#include <bits/stdc++.h>
24+
typedef long long ll;
25+
using namespace std;
26+
27+
int depth[2000001], mx_child[2000001];
28+
vector<int> children[2000001];
29+
30+
int main() {
31+
cin.tie(0)->sync_with_stdio(0);
32+
int n, d, tx;
33+
cin >> n >> d >> tx;
34+
35+
int ans = n, glob_mx = 0, loc_mx = 0;
36+
priority_queue<pair<int, int>> pq;
37+
stack<pair<int, int>> stck;
38+
for (int i = 1; i <= n; i++) {
39+
int t;
40+
cin >> t;
41+
glob_mx = max(glob_mx, i + tx - t);
42+
loc_mx = max(loc_mx, i + tx - t);
43+
if (stck.size())
44+
stck.top().second = max(stck.top().second, loc_mx);
45+
if (t > tx) {
46+
if (glob_mx < i) ans--;
47+
else {
48+
depth[i] = 1;
49+
while (stck.size()) {
50+
int node, tmp_mx;
51+
tie(node, tmp_mx) = stck.top();
52+
if (tmp_mx >= i) break;
53+
children[i].push_back(node);
54+
if (depth[node] + 1 > depth[i]) {
55+
depth[i] = depth[node] + 1;
56+
mx_child[i] = node;
57+
}
58+
stck.pop();
59+
if (stck.size())
60+
stck.top().second = max(stck.top().second, tmp_mx);
61+
}
62+
loc_mx = i + tx - t;
63+
stck.push({i, loc_mx});
64+
}
65+
}
66+
}
67+
while (stck.size()) {
68+
int root = stck.top().first;
69+
pq.push({depth[root], root});
70+
stck.pop();
71+
}
72+
73+
while (d-- && pq.size()) {
74+
pair<int, int> curr = pq.top();
75+
pq.pop();
76+
ans -= curr.first;
77+
int node = curr.second;
78+
while (node) {
79+
for (int i : children[node]) if (i != mx_child[node])
80+
pq.push({depth[i], i});
81+
node = mx_child[node];
82+
}
83+
}
84+
cout << ans;
85+
return 0;
86+
}

0 commit comments

Comments
 (0)