Submission #1230957

#TimeUsernameProblemLanguageResultExecution timeMemory
1230957long290429Factories (JOI14_factories)C++20
0 / 100
1822 ms111672 KiB
#include<bits/stdc++.h>
using namespace std;
const int maxn=500005;
int tin[maxn],tout[maxn];
int dep[maxn],dtr[maxn];
vector<pair<int,int>> adj[maxn];
int tt,lg;
vector<vector<int>> up;
long long inf=LLONG_MAX/4,ans;
void dfs(int u,int par) {
  tin[u]=++tt;
  up[u][0]=par;
  for(int i=1;i<=lg;++i) {
    if(up[u][i-1]!=-1) {
      up[u][i]=up[up[u][i-1]][i-1];
    }
    else break;
  }
  for(pair<int,int> p:adj[u]) {
    int v=p.first,w=p.second;
    if(v==par) 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 k=dep[u]-dep[v];
  for(int i=0;k>0;++i) {
    if(k&1) {
      u=up[u][i];
    }
    k>>=1;
  }
  if(u==v) return u;
  for(int i=lg;i>=0;--i) {
    if(up[u][i]!=-1&&up[v][i]!=-1&&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) gom tất cả nút của A và B vào cùng 1 vector
    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 và thêm LCA của các cặp liền kề
    sort(vs.begin(), vs.end(), [&](int u, int v){
        return tin[u] < tin[v];
    });
    int K = vs.size();
    for(int i = 1; i < K; i++){
        int u = vs[i-1], v = vs[i];
        vs.push_back(lca(u, v));
    }

    // 3) unique lại và sort theo tin nữa
    sort(vs.begin(), vs.end(), [&](int u, int v){
        return tin[u] < tin[v];
    });
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    int sz = vs.size();

    // 4) đánh số lại (node -> idx)
    unordered_map<int,int> idx;
    idx.reserve(sz * 1.3);
    vector<vector<pair<int,int>>> vt(sz);
    for(int i = 0; i < sz; i++){
        idx[vs[i]] = i;
        vt[i].clear();
    }

    // 5) build virtual tree bằng stack
    static vector<int> st;
    
    st.clear();
    for(int i = 0; i < sz; i++){
        int u = vs[i];
        int 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].push_back({idu, (int)w});
            vt[idu].push_back({top, (int)w});
        }
        st.push_back(idu);
    }

    // 6) multi-source init
    const long long INF = LLONG_MAX/4;
    static vector<long long> da, db;
    da.assign(sz, INF);
    db.assign(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;

    // 7) two-pass DP trên cây để lấy min(da[x]+db[x])
    long long ans = INF;
    function<void(int,int)> dfs1 = [&](int u, int p){
        for(auto &e : vt[u]){
            int v = e.first, 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]);
    };
    function<void(int,int)> dfs2 = [&](int u, int p){
        for(auto &e : vt[u]){
            int v = e.first, 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);
        }
    };
    // st[0] chứa idx của nút có tin nhỏ nhất => gốc virtual tree
    dfs1(st[0], -1);
    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]].push_back({v[i],w[i]});
    adj[v[i]].push_back({u[i],w[i]});
  }
  tt=0;
  dep[0]=0;
  dtr[0]=0;
  lg=floor(log2(n));
  up.assign(n,vector<int>(lg+1,-1));
  dfs(0,-1);
}
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...