Submission #1230970

#TimeUsernameProblemLanguageResultExecution timeMemory
1230970long290429Factories (JOI14_factories)C++20
100 / 100
2279 ms153288 KiB
#include <bits/stdc++.h>
using namespace std;

const int MAXN = 500000;
int N, Q;

// cây ban đầu
vector<pair<int,long long>> adj[MAXN];
int tin[MAXN], tout[MAXN], dep[MAXN];
long long dtr[MAXN];
int tt, lg;
vector<vector<int>> up;

// DFS build LCA, tính tin/tout và dtr[]
void dfs(int u, int p) {
    tin[u] = ++tt;
    up[u][0] = p;
    for(int i = 1; i <= lg; i++) {
        int pi = up[u][i-1];
        up[u][i] = (pi < 0 ? -1 : up[pi][i-1]);
    }
    for(auto &e : adj[u]) {
        int v = e.first;
        long long w = e.second;
        if (v == p) continue;
        dep[v] = dep[u] + 1;
        dtr[v] = dtr[u] + w;
        dfs(v, u);
    }
    tout[u] = tt;
}

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++, diff >>= 1)
        if (diff & 1) u = up[u][i];
    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];
}

const long long INF = (long long)4e18;

// solve cho 1 query: tập A cỡ n, tập B cỡ m
long long solve(int A[], int n, int B[], int m) {
    // 1) gom chung
    vector<int> vs;
    vs.reserve(n + m);
    for(int i = 0; i < n; i++) vs.push_back(A[i]);
    for(int i = 0; i < m; i++) vs.push_back(B[i]);

    // 2) sort theo tin rồi thêm LCA của cặp liền kề
    sort(vs.begin(), vs.end(), [&](int x,int y){ return tin[x] < tin[y]; });
    int K = vs.size();
    for(int i = 1; i < K; i++)
        vs.push_back(lca(vs[i-1], vs[i]));

    // 3) unique + sort lại
    sort(vs.begin(), vs.end(), [&](int x,int y){ return tin[x] < tin[y]; });
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    int sz = vs.size();

    // 4) đánh chỉ số
    unordered_map<int,int> idx;
    idx.reserve(sz*1.3);
    for(int i = 0; i < sz; i++) idx[vs[i]] = i;

    // 5) build virtual-tree
    vector<vector<pair<int,long long>>> vt(sz);
    vector<int> st;
    st.reserve(sz);
    for(int i = 0; i < sz; i++){
        int u = vs[i], idu = i;
        while(!st.empty()) {
            int top = st.back();
            int v = vs[top];
            if (tin[v] <= tin[u] && tout[u] <= tout[v]) break;
            st.pop_back();
        }
        if (!st.empty()) {
            int top = st.back();
            int v = vs[top];
            long long w = dtr[u] - dtr[v];
            vt[top].emplace_back(idu, w);
            vt[idu].emplace_back(top, w);
        }
        st.push_back(idu);
    }

    // 6) multi-source init
    vector<long long> da(sz, INF), db(sz, 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;
    // post-order
    function<void(int,int)> dfs1 = [&](int u, int p){
        for(auto &e: vt[u]) {
            int v = e.first;
            long long w = e.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]);
    };
    // pre-order
    function<void(int,int)> dfs2 = [&](int u, int p){
        for(auto &e: vt[u]) {
            int v = e.first;
            long long w = e.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);
        }
    };

    int root = st.front();
    dfs1(root, -1);
    dfs2(root, -1);

    return ans;
}

// được gọi 1 lần
void Init(int N, int U[], int V[], int D[]) {
    ::N = N;
    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], (long long)D[i]);
        adj[V[i]].emplace_back(U[i], (long long)D[i]);
    }
    tt = 0;
    dep[0] = dtr[0] = 0;
    lg = floor(log2(N));
    up.assign(N, vector<int>(lg+1, -1));
    dfs(0, -1);
}

// được gọi Q lần
long long Query(int S, int X[], int T, int Y[]) {
    return solve(X, S, Y, T);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...