제출 #1299129

#제출 시각아이디문제언어결과실행 시간메모리
1299129cnam9Cat Exercise (JOI23_ho_t4)C++20
100 / 100
138 ms45000 KiB
#include <iostream>
#include <vector>
#include <math.h>

using namespace std;

constexpr int N = 2e5 + 5;
constexpr int logN = static_cast<int>(log2(N));

int n;
int at[N];
vector<int> tree[N];

int timer;
int tin[N], tout[N];
int depth[N];
int up[N][logN + 1];

void dfs(int u, int p) {
    up[u][0] = p;
    for (int i = 0; i < logN; i++) {
        up[u][i + 1] = up[up[u][i]][i];
    }

    tin[u] = ++timer;
    for (int v : tree[u]) {
        if (v == p) continue;
        depth[v] = depth[u] + 1;
        dfs(v, u);
    }
    tout[u] = timer;
}

inline bool is_ancestor(int a, int d) {
    return tin[a] <= tin[d] && tin[d] <= tout[a];
}

int lca(int u, int v) {
    if (is_ancestor(u, v)) return u;
    if (is_ancestor(v, u)) return v;

    for (int i = logN; i >= 0; i--) {
        if (is_ancestor(up[u][i], v)) continue;
        u = up[u][i];
    }
    return up[u][0];
}

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

long long dp[N];
int headquarter[N];
int parent[N];
int renk[N];

inline bool is_set(int u) {
    return parent[u] != 0;
}

inline void make_set(int u) {
    parent[u] = u;
}

int find_set(int u) {
    if (parent[u] == u) return u;
    return parent[u] = find_set(parent[u]);
}

inline void union_sets(int u, int v) {
    u = find_set(u);
    v = find_set(v);

    if (renk[u] >= renk[v]) {
        if (renk[u] == renk[v]) renk[v]++;
        parent[v] = u;
    } else {
        parent[u] = v;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);

    // freopen("input.txt", "r", stdin);

    cin >> n;

    for (int u = 1; u <= n; u++) {
        int h;
        cin >> h;
        at[h] = u;
    }

    for (int e = 1; e < n; e++) {
        int u, v;
        cin >> u >> v;

        tree[u].push_back(v);
        tree[v].push_back(u);
    }

    dfs(1, 1);

    for (int h = 1; h <= n; h++) {
        int u = at[h];

        long long maxd = 0;
        make_set(u);
        for (int v : tree[u]) {
            if (!is_set(v)) continue;
            maxd = max(maxd, dp[find_set(v)] + dist(u, headquarter[find_set(v)]));
            union_sets(u, v);
        }
        dp[find_set(u)] = maxd;
        headquarter[find_set(u)] = u;
    }

    cout << dp[at[n]];

    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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...