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;
}
  |