Submission #1378849

#TimeUsernameProblemLanguageResultExecution timeMemory
1378849Francisco_MartinAPIOBike (APIO26_bike)C++20
100 / 100
293 ms108356 KiB
#include "bike.h"
#include <bits/stdc++.h>

using namespace std;

std::pair<std::vector<int>, std::vector<long long>>
find_rebalancing_strategy(int N, std::vector<int> A, std::vector<int> B, 
                          std::vector<int> U, std::vector<int> V) {
    vector<vector<int>> g(N);
    for (int i = 0; i < N - 1; i++) {
        int u = U[i], v = V[i];
        g[u].push_back(v);
        g[v].push_back(u);
    }

    vector<bool> done(N, false);
    int st = -1, ed = -1, cost = -1;
    int remain_vertex = N;
    
    int rt = -1;
    for (int i = 0; i < N; i++) {
        if (A[i] != B[i]) {
            rt = i;
            break;
        }
    }
    
    if (rt == -1) return {{}, {}};

    vector<long long> subtree(N, 0);
    
    auto dfs1 = [&](auto self, int now, int p) -> pair<pair<int, int>, pair<int, int>> {
        pair<int, int> max_up(0, now);
        pair<int, int> max_down(0, now);
        subtree[now] = A[now] - B[now];
        bool bad = false;
        
        for (int i : g[now]) {
            if (i == p) continue;
            auto [up, down] = self(self, i, now);
            int tmp = up.first + max_down.first;
            if (tmp > cost) cost = tmp, st = up.second, ed = max_down.second;
            
            tmp = down.first + max_up.first;
            if (tmp > cost) cost = tmp, st = max_up.second, ed = down.second;
            
            max_up = max(max_up, up);
            max_down = max(max_down, down);
            subtree[now] += subtree[i];
            bad = bad || !done[i];
        }
        
        if (!bad && A[now] == B[now]) {
            done[now] = true;
            remain_vertex--;
            max_up = {-1, now};
            max_down = {-1, now};
        } else {
            if (subtree[now] >= 0) max_up.first++;
            else max_up.first--;
            if (subtree[now] <= 0) max_down.first++;
            else max_down.first--;
        }
        return {max_up, max_down};
    };
    
    dfs1(dfs1, rt, rt);

    vector<long long> subtree_diff(N, 0);
    vector<int> path;
    auto dfs_path = [&](auto self, int now, int p) -> bool {
        subtree_diff[now] = A[now] - B[now];
        bool ok = (now == ed);
        for (int i : g[now]) {
            if (i == p) continue;
            ok = self(self, i, now) || ok;
            subtree_diff[now] += subtree_diff[i];
        }
        if (ok) path.push_back(now);
        return ok;
    };
    
    dfs_path(dfs_path, st, st);
    reverse(path.begin(), path.end());
    
    vector<int> path_index(N, -1);
    for (int i = 0; i < (int)path.size(); i++) {
        path_index[path[i]] = i;
    }

    vector<int> X;
    vector<long long> Y;
    
    auto walk = [&](int v, long long amount) {
        if (X.empty() || X.back() != v) {
            X.push_back(v);
            Y.push_back(0);
        }
        Y.back() += amount;
        A[v] += amount;
    };

    for (int i = 0; i < N; i++) {
        int ptr = 0;
        for (int j = 0; j < (int)g[i].size(); j++) {
            if (subtree_diff[g[i][j]] > 0) {
                swap(g[i][ptr++], g[i][j]);
            }
        }
    }

    auto dfs2 = [&](auto self, int now, int p) -> void {
        walk(now, -A[now]);
        for (int i : g[now]) {
            if (i == p || done[i]) continue;
            self(self, i, now);
            X.push_back(now);
            Y.push_back(0);
        }
        walk(now, B[now]);
    };

    for (int i = 0; i < (int)path.size(); i++) {
        vector<int> todo;
        while (i + 1 < (int)path.size() && subtree_diff[path[i + 1]] > 0) {
            int cur = path[i];
            walk(cur, -A[cur]);
            todo.push_back(cur);
            i++;
        }
        todo.push_back(path[i]);

        for (int j = (int)todo.size() - 1; j >= 0; j--) {
            int now = todo[j];
            walk(now, -A[now]);
            for (int v : g[now]) {
                if (path_index[v] == -1 && !done[v]) {
                    dfs2(dfs2, v, now);
                }
                walk(now, 0);
            }
        }
        for (int now : todo) {
            walk(now, B[now]);
        }
    }
    
    return {X, Y};
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...