Submission #1298902

#TimeUsernameProblemLanguageResultExecution timeMemory
1298902kenkunkinThe Xana coup (BOI21_xanadu)C++20
0 / 100
60 ms17440 KiB
#include <bits/stdc++.h>
using namespace std;

void Init()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}

typedef long long ll;
const int MAXN = 200000 + 5;
const ll INF = (ll)4e18;

int n;
vector<int> g[MAXN];
int initState[MAXN]; // 0 = off, 1 = on
ll dp[MAXN][2][2];   // dp[v][parentPress][pressV]
int parentArr[MAXN];

void Input()
{
    cin >> n;
    for (int i = 1; i <= n; ++i) {
        g[i].clear();
        initState[i] = 0;
    }
    for (int i = 0; i < n - 1; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    string token;
    cin >> token;
    if ((int)token.size() == n) {
        for (int i = 1; i <= n; ++i) initState[i] = token[i-1] - '0';
    } else {
        initState[1] = stoi(token);
        for (int i = 2; i <= n; ++i) cin >> initState[i];
    }
}

void dfs(int v, int p)
{
    parentArr[v] = p;
    for (int to : g[v]) if (to != p) dfs(to, v);

    // compute dp[v][parentPress][pressV]
    // follow editorial: tmp[pressV][parity]
    for (int parentPress = 0; parentPress <= 1; ++parentPress) {
        for (int pressV = 0; pressV <= 1; ++pressV) {
            // actually will compute after merging children
            // but we will compute tmp independent of parentPress, using pressV in indexing as in editorial.
        }
    }

    // For each possible pressV (this is the "v pressed or not" value used when merging child's parentPress)
    // We compute tmp[0/1][0/1] as editorial describes, but need values for both parentPress later.
    // Implementation: for each parentPress i and pressV j we need tmp[*][j], where tmp indices first dim 0/1 correspond to whether v is pressed in the tmp's meaning.
    // The editorial uses tmp[0][0], tmp[0][1], tmp[1][0], tmp[1][1] where first index = whether v pressed, second = parity.
    // Build tmp for both pressV = 0 and pressV = 1 simultaneously by running loop for pressV.
    for (int pv = 0; pv <= 1; ++pv) {
        ll tmp[2][2];
        tmp[0][0] = 0;
        tmp[0][1] = INF;
        tmp[1][0] = 0;
        tmp[1][1] = INF;

        for (int to : g[v]) {
            if (to == p) continue;
            ll ntmp[2][2];
            ntmp[0][0] = ntmp[0][1] = ntmp[1][0] = ntmp[1][1] = INF;

            // apply editorial merge formulas (child's parentPress values are 0 or 1)
            // Note: dp[to][a][b] means for child 'to', parentPress = a, pressChild = b.
            // When computing tmp[0][0] (v not pressed, even), editorial uses dp[0][1][to] and dp[0][0][to], etc.
            // Implement directly:
            // tmp[0][0] = min(tmp[1][0] + dp[0][1][to], tmp[0][0] + dp[0][0][to])
            ntmp[0][0] = min(
                tmp[1][0] >= INF || dp[to][0][1] >= INF ? INF : tmp[1][0] + dp[to][0][1],
                tmp[0][0] >= INF || dp[to][0][0] >= INF ? INF : tmp[0][0] + dp[to][0][0]
            );

            // tmp[0][1] = min(tmp[1][1] + dp[1][1][to], tmp[0][1] + dp[1][0][to])
            ntmp[0][1] = min(
                tmp[1][1] >= INF || dp[to][1][1] >= INF ? INF : tmp[1][1] + dp[to][1][1],
                tmp[0][1] >= INF || dp[to][1][0] >= INF ? INF : tmp[0][1] + dp[to][1][0]
            );

            // tmp[1][0] = min(tmp[0][0] + dp[0][1][to], tmp[1][0] + dp[0][0][to])
            ntmp[1][0] = min(
                tmp[0][0] >= INF || dp[to][0][1] >= INF ? INF : tmp[0][0] + dp[to][0][1],
                tmp[1][0] >= INF || dp[to][0][0] >= INF ? INF : tmp[1][0] + dp[to][0][0]
            );

            // tmp[1][1] = min(tmp[0][1] + dp[1][1][to], tmp[1][1] + dp[1][0][to])
            ntmp[1][1] = min(
                tmp[0][1] >= INF || dp[to][1][1] >= INF ? INF : tmp[0][1] + dp[to][1][1],
                tmp[1][1] >= INF || dp[to][1][0] >= INF ? INF : tmp[1][1] + dp[to][1][0]
            );

            tmp[0][0] = min(tmp[0][0], ntmp[0][0]); // keep best (defensive)
            tmp[0][1] = min(tmp[0][1], ntmp[0][1]);
            tmp[1][0] = min(tmp[1][0], ntmp[1][0]);
            tmp[1][1] = min(tmp[1][1], ntmp[1][1]);
            // Actually assign to ntmp to continue correctly
            tmp[0][0] = ntmp[0][0];
            tmp[0][1] = ntmp[0][1];
            tmp[1][0] = ntmp[1][0];
            tmp[1][1] = ntmp[1][1];
        }

        // Now tmp corresponds to the case "v pressed = pv" in editorial indexing.
        // For each possible parentPress i and pressV j we will read tmp[pv][j] or tmp[1][j] depending on need.
        // Store interim results in a temp array by pv
        // We'll write these into dp[v] after finishing pv loop for both pv=0,1
        // To simplify, store tmp results into a small array
        // Save into dp_temp_for_pv[pv][parity]
        // Use a static local container:
        static ll saved_tmp[2][2][2];
        for (int parity = 0; parity <= 1; ++parity) {
            saved_tmp[pv][0][parity] = tmp[0][parity];
            saved_tmp[pv][1][parity] = tmp[1][parity];
        }
        // After finishing pv loops, will use saved_tmp to compute dp[v][*][*].
        // BUT note: saved_tmp is static and must carry across iterations; copy out now.
        // We'll handle assignment outside of this pv loop by storing into dp using saved_tmp references.
        // To avoid complexity, copy saved_tmp into dp after both pv iterations.
        if (pv == 1) {
            // retrieve both pv=0 and pv=1 saved tmp values
            ll t00 = saved_tmp[0][0][0];
            ll t01 = saved_tmp[0][0][1];
            ll t10 = saved_tmp[0][1][0];
            ll t11 = saved_tmp[0][1][1];
            ll s00 = saved_tmp[1][0][0];
            ll s01 = saved_tmp[1][0][1];
            ll s10 = saved_tmp[1][1][0];
            ll s11 = saved_tmp[1][1][1];

            // Compute dp[v][parentPress][pressV] for all 4 combinations
            for (int i = 0; i <= 1; ++i) {
                for (int j = 0; j <= 1; ++j) {
                    int toggles = (i + j) & 1;
                    int needParity = initState[v] ^ toggles; // 0 -> children even, 1 -> children odd

                    // choose tmp corresponding to pressV = j
                    if (j == 0) {
                        // tmp for pv=0: t**
                        if (needParity == 0) dp[v][i][j] = (ll)j + ( (t00 >= INF) ? INF : t00 );
                        else dp[v][i][j] = (ll)j + ( (t01 >= INF) ? INF : t01 );
                    } else {
                        // tmp for pv=1: s**
                        if (needParity == 0) dp[v][i][j] = (ll)j + ( (s10 >= INF) ? INF : s10 ); // careful mapping
                        else dp[v][i][j] = (ll)j + ( (s11 >= INF) ? INF : s11 );
                        // Note: s10/s11 correspond to saved_tmp[1][1][parity] etc.
                        // However earlier saved_tmp layout: saved_tmp[pv][x][parity] where x indexes ??? 
                        // To avoid confusion, recompute properly below using a safe approach.
                    }
                }
            }
            // The above has confusion due to saved_tmp indexing chosen. Instead recompute dp directly using fresh tmp builds per (pressV).
        }
    }

    // Simpler and correct approach: rebuild tmp separately for pressV=0 and pressV=1 and then compute dp.
    // Do that cleanly here (overwrite dp[v] with correct values).
    // Recompute tmp for pv=0
    {
        ll tmp0[2] = {0, INF}; // tmp when v not pressed: tmp0[parity]
        for (int to : g[v]) {
            if (to == p) continue;
            ll n0[2] = {INF, INF};
            // tmp0_even = min(prev_odd + dp[to][0][1], prev_even + dp[to][0][0])
            n0[0] = min(
                tmp0[1] >= INF || dp[to][0][1] >= INF ? INF : tmp0[1] + dp[to][0][1],
                tmp0[0] >= INF || dp[to][0][0] >= INF ? INF : tmp0[0] + dp[to][0][0]
            );
            // tmp0_odd = min(prev_odd + dp[to][1][1], prev_even + dp[to][1][0]) -- note editorial's formula used tmp[1][1] + dp[1][1] and tmp[0][1] + dp[1][0]
            // But correct merging for tmp[0][1] as per editorial:
            n0[1] = min(
                tmp0[1] >= INF || dp[to][1][1] >= INF ? INF : tmp0[1] + dp[to][1][1],
                tmp0[0] >= INF || dp[to][1][0] >= INF ? INF : tmp0[0] + dp[to][1][0]
            );
            tmp0[0] = n0[0];
            tmp0[1] = n0[1];
        }

        ll tmp1[2] = {0, INF}; // tmp when v pressed
        for (int to : g[v]) {
            if (to == p) continue;
            ll n1[2] = {INF, INF};
            n1[0] = min(
                tmp1[1] >= INF || dp[to][0][1] >= INF ? INF : tmp1[1] + dp[to][0][1],
                tmp1[0] >= INF || dp[to][0][0] >= INF ? INF : tmp1[0] + dp[to][0][0]
            );
            n1[1] = min(
                tmp1[1] >= INF || dp[to][1][1] >= INF ? INF : tmp1[1] + dp[to][1][1],
                tmp1[0] >= INF || dp[to][1][0] >= INF ? INF : tmp1[0] + dp[to][1][0]
            );
            tmp1[0] = n1[0];
            tmp1[1] = n1[1];
        }

        for (int i = 0; i <= 1; ++i) {
            for (int j = 0; j <= 1; ++j) {
                int toggles = (i + j) & 1;
                int needParity = initState[v] ^ toggles;
                if (j == 0) {
                    if (needParity == 0) dp[v][i][j] = (ll)j + tmp0[0];
                    else dp[v][i][j] = (ll)j + tmp0[1];
                } else {
                    if (needParity == 0) dp[v][i][j] = (ll)j + tmp1[0];
                    else dp[v][i][j] = (ll)j + tmp1[1];
                }
                if (dp[v][i][j] > INF) dp[v][i][j] = INF;
            }
        }
    }
}

void Bai()
{
    // choose root = 1
    dfs(1, 0);
    ll ans = min(dp[1][0][0], dp[1][0][1]);
    if (ans >= INF/2) cout << -1 << '\n';
    else cout << ans << '\n';
}

int main()
{
    Init();
    Input();
    Bai();
    return 0;
}
#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...