Submission #1230896

#TimeUsernameProblemLanguageResultExecution timeMemory
1230896long290429Factories (JOI14_factories)C++20
0 / 100
1867 ms111692 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 500000 + 5;
int tin[MAXN], tout[MAXN], timer;
int dep[MAXN], dtr[MAXN];
vector<pair<int,int>> adj[MAXN];
int lg;
vector<vector<int>> up;

void dfs(int u, int p) {
    tin[u] = ++timer;
    up[u][0] = p;
    for (int i = 1; i <= lg; ++i) {
        int mid = up[u][i-1];
        if (mid < 0) break;
        up[u][i] = up[mid][i-1];
    }
    for (auto &e : adj[u]) {
        int v = e.first, w = e.second;
        if (v == p) continue;
        dep[v] = dep[u] + 1;
        dtr[v] = dtr[u] + w;
        dfs(v, u);
    }
    tout[u] = timer;
}

int lca(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    int diff = dep[u] - dep[v];
    for (int i = 0; diff; ++i) {
        if (diff & 1) u = up[u][i];
        diff >>= 1;
    }
    if (u == v) return u;
    for (int i = lg; i >= 0; --i) {
        if (up[u][i] != up[v][i]) {
            u = up[u][i];
            v = up[v][i];
        }
    }
    return up[u][0];
}

long long solve(int a[], int n, int b[], int m) {
    // 1) collect nodes and add LCA of original neighbors
    vector<int> nodes;
    nodes.insert(nodes.end(), a, a + n);
    nodes.insert(nodes.end(), b, b + m);
    sort(nodes.begin(), nodes.end(), [&](int u, int v){ return tin[u] < tin[v]; });
    int orig = nodes.size();
    for (int i = 1; i < orig; ++i) {
        nodes.push_back(lca(nodes[i-1], nodes[i]));
    }
    sort(nodes.begin(), nodes.end(), [&](int u, int v){ return tin[u] < tin[v]; });
    nodes.erase(unique(nodes.begin(), nodes.end()), nodes.end());
    int K = nodes.size();

    // 2) map and build virtual tree
    unordered_map<int,int> idx;
    idx.reserve(K);
    for (int i = 0; i < K; ++i) idx[nodes[i]] = i;

    vector<vector<pair<int,int>>> vt(K);
    vector<int> st;
    for (int u : nodes) {
        int uid = idx[u];
        while (!st.empty() && !(tin[nodes[st.back()]] <= tin[u] && tout[u] <= tout[nodes[st.back()]]))
            st.pop_back();
        if (!st.empty()) {
            int pid = st.back();
            int p = nodes[pid];
            int w = dtr[u] - dtr[p];
            vt[pid].emplace_back(uid, w);
            vt[uid].emplace_back(pid, w);
        }
        st.push_back(uid);
    }

    // 3) DP on virtual tree
    const long long INF = LLONG_MAX / 4;
    vector<long long> da(K, INF), db(K, INF);
    for (int i = 0; i < n; ++i) da[idx[a[i]]] = 0;
    for (int i = 0; i < m; ++i) db[idx[b[i]]] = 0;

    long long ans = INF;
    function<void(int,int)> dfs1 = [&](int u, int p) {
        for (auto &pr : vt[u]) {
            int v = pr.first, w = pr.second;
            if (v == p) continue;
            dfs1(v, u);
            da[u] = min(da[u], da[v] + w);
            db[u] = min(db[u], db[v] + w);
        }
        ans = min(ans, da[u] + db[u]);
    };
    dfs1(st[0], -1);

    function<void(int,int)> dfs2 = [&](int u, int p) {
        for (auto &pr : vt[u]) {
            int v = pr.first, w = pr.second;
            if (v == p) continue;
            da[v] = min(da[v], da[u] + w);
            db[v] = min(db[v], db[u] + w);
            ans = min(ans, da[v] + db[v]);
            dfs2(v, u);
        }
    };
    dfs2(st[0], -1);

    return ans;
}

void Init(int n, int U[], int V[], int W[]) {
    for (int i = 0; i < n; ++i) adj[i].clear();
    for (int i = 0; i < n-1; ++i) {
        adj[U[i]].emplace_back(V[i], W[i]);
        adj[V[i]].emplace_back(U[i], W[i]);
    }
    timer = 0;
    fill(dep, dep+n, 0);
    fill(dtr, dtr+n, 0);
    lg = floor(log2(max(1, n)));
    up.assign(n, vector<int>(lg+1, -1));
    dfs(0, -1);
}

long long Query(int s, int A[], int t, int B[]) {
    return solve(A, s, B, t);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...