Submission #274869

#TimeUsernameProblemLanguageResultExecution timeMemory
274869smaxFactories (JOI14_factories)C++17
100 / 100
7971 ms224112 KiB
#include "factories.h"
#include <bits/stdc++.h>
using namespace std;

#define MAXN 500005

const long long INF = 1e18;

struct CentroidDecomposition {
    vector<int> sub, par;
    vector<bool> visited;
    vector<vector<int>> adj;

    CentroidDecomposition() {}

    CentroidDecomposition(int n) : sub(n), par(n), visited(n), adj(n) {}

    void addEdge(int u, int v) {
        adj[u].push_back(v);
        adj[v].push_back(u);
    }

    void build(int u = 0, int p = -1) {
        u = centroid(u, p, dfs(u, p));
        par[u] = p;
        visited[u] = true;
        for (int v : adj[u])
            if (!visited[v])
                build(v, u);
    }

    int dfs(int u, int p) {
        sub[u] = 1;
        for (int v : adj[u])
            if (v != p && !visited[v])
                sub[u] += dfs(v, u);
        return sub[u];
    }

    int centroid(int u, int p, int sz) {
        for (int v : adj[u])
            if (v != p && !visited[v] && sub[v] > sz / 2)
                return centroid(v, u, sz);
        return u;
    }

    int operator [] (int i) const {
        return par[i];
    }
};

struct RMQ {
    vector<long long> a;
    vector<vector<int>> spt;

    void init(int n, long long *_a) {
        a.resize(n);
        spt.assign(1, vector<int>(n));
        for (int i=0; i<n; i++) {
            a[i] = _a[i];
            spt[0][i] = i;
        }

        for (int j=1; 1<<j<=n; j++) {
            spt.emplace_back(n - (1 << j) + 1);
            for (int i=0; i+(1<<j)<=n; i++) {
                if (a[spt[j-1][i]] < a[spt[j-1][i+(1<<(j-1))]])
                    spt[j][i] = spt[j-1][i];
                else
                    spt[j][i] = spt[j-1][i+(1<<(j-1))];
            }
        }
    }

    int query(int i, int j) {
        int k = 31 - __builtin_clz(j - i + 1);
        if (a[spt[k][i]] < a[spt[k][j-(1<<k)+1]])
            return spt[k][i];
        else
            return spt[k][j-(1<<k)+1];
    }
};

int idx, ti[MAXN], node[2*MAXN];
long long depth[2*MAXN];
vector<pair<int, int>> adj[MAXN];
RMQ rmq;

void dfs(int u, int p, long long d) {
    ti[u] = idx;
    node[idx] = u;
    depth[idx++] = d;
    for (auto &e : adj[u])
        if (e.first != p) {
            dfs(e.first, u, d + e.second);
            node[idx] = u;
            depth[idx++] = d;
        }
}

int lca(int u, int v) {
    if (ti[u] > ti[v])
        swap(u, v);
    return node[rmq.query(ti[u], ti[v])];
}

long long dist(int u, int v) {
    return depth[ti[u]] + depth[ti[v]] - 2 * depth[ti[lca(u, v)]];
}

void preprocess() {
    idx = 0;
    dfs(0, -1, 0);
    rmq.init(idx, depth);
}

long long ans[MAXN];
CentroidDecomposition cd;

void Init(int N, int A[], int B[], int D[]) {
    cd = CentroidDecomposition(N);
    for (int i=0; i<N-1; i++) {
        cd.addEdge(A[i], B[i]);
        adj[A[i]].emplace_back(B[i], D[i]);
        adj[B[i]].emplace_back(A[i], D[i]);
    }
    cd.build();
    preprocess();
    for (int i=0; i<N; i++)
        ans[i] = INF;
}

long long Query(int S, int X[], int T, int Y[]) {
    for (int i=0; i<S; i++) {
        int u = X[i];
        while (u != -1) {
            ans[u] = min(ans[u], dist(X[i], u));
            u = cd[u];
        }
    }
    long long ret = INF;
    for (int i=0; i<T; i++) {
        int u = Y[i];
        while (u != -1) {
            ret = min(ret, ans[u] + dist(Y[i], u));
            u = cd[u];
        }
    }
    for (int i=0; i<S; i++) {
        int u = X[i];
        while (u != -1) {
            ans[u] = INF;
            u = cd[u];
        }
    }
    return ret;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...