1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| // 더 많은 정보와 풀이 해설은 42jerrykim.github.io에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<int> capacity(n + 1);
for (int i = 1; i <= n; ++i) cin >> capacity[i];
vector<int> start(m + 1);
for (int i = 1; i <= m; ++i) cin >> start[i];
const int MAX_IDX = 2 * n + 5;
const int INF = 1e9;
vector<int> remainingFood(MAX_IDX, 0);
vector<int> bestDistanceInSubtree(MAX_IDX, INF);
vector<int> bestNodeInSubtree(MAX_IDX, 0);
vector<int> flowAlongEdge(MAX_IDX, 0);
auto leftChild = [](int u) { return u << 1; };
auto rightChild = [](int u) { return (u << 1) | 1; };
auto costUp = [&](int u) -> int {
return (flowAlongEdge[u] < 0) ? -1 : 1;
};
auto costDown = [&](int child) -> int {
return (flowAlongEdge[child] > 0) ? -1 : 1;
};
for (int i = 1; i <= n; ++i) remainingFood[i] = capacity[i];
function<void(int)> updateNode = [&](int u) {
int bestPos = 0;
int bestDis = INF;
if (u <= n && remainingFood[u] > 0) {
bestPos = u;
bestDis = 0;
}
int lc = leftChild(u);
int cand = bestDistanceInSubtree[lc];
if (cand < INF) {
int v = cand + costDown(lc);
if (v < bestDis) {
bestDis = v;
bestPos = bestNodeInSubtree[lc];
}
}
int rc = rightChild(u);
cand = bestDistanceInSubtree[rc];
if (cand < INF) {
int v = cand + costDown(rc);
if (v < bestDis) {
bestDis = v;
bestPos = bestNodeInSubtree[rc];
}
}
bestDistanceInSubtree[u] = bestDis;
bestNodeInSubtree[u] = bestPos;
};
for (int u = n; u >= 1; --u) updateNode(u);
long long totalCost = 0;
for (int i = 1; i <= m; ++i) {
int x = start[i];
int z = 0;
int now = 0;
int best = INF;
for (int u = x; u >= 1; u >>= 1) {
int val = now + bestDistanceInSubtree[u];
if (val < best) {
best = val;
z = u;
}
if (u > 1) now += costUp(u);
}
int y = bestNodeInSubtree[z];
totalCost += best;
--remainingFood[y];
for (int u = x; u != z; u >>= 1) ++flowAlongEdge[u];
for (int u = y; u != z; u >>= 1) --flowAlongEdge[u];
for (int u = y; u != z; u >>= 1) updateNode(u);
for (int u = x; u >= 1; u >>= 1) updateNode(u);
if (i > 1) cout << ' ';
cout << totalCost;
}
cout << '\n';
return 0;
}
|