제출 #782830

#제출 시각아이디문제언어결과실행 시간메모리
782830thimote75Cat Exercise (JOI23_ho_t4)C++14
100 / 100
451 ms72960 KiB

#include <bits/stdc++.h>
#define int long long

using namespace std;

using idata = vector<int>;
using igrid = vector<idata>;

struct UFD {
    idata parents;

    UFD (int size) {
        parents.resize(size);
        iota(parents.begin(), parents.end(), 0);
    }
    int boss (int x) {
        if (parents[x] != x)
            parents[x] = boss(parents[x]);
        return parents[x];
    }
    void merge (int a, int b) {
        a = boss(a);
        b = boss(b);
        if (a < b) swap (a, b);

        parents[b] = a;
    }
};

const int MAXK = 20;
int N;

idata depth;
idata parents;
igrid parents_2k;

igrid roads;

void dfs (int node, int parent, int _depth) {
    depth     [node]    = _depth;
    parents   [node]    = parent;
    parents_2k[node][0] = parent;

    for (int next : roads[node]) if (next != parent)
        dfs(next, node, _depth + 1);
}
void init_lca () {
    for (int k = 0; k + 1 < MAXK; k ++) {
        for (int i = 0; i < N; i ++) {
            if (parents_2k[i][k] == -1) continue ;

            parents_2k[i][k + 1]
             = parents_2k[parents_2k[i][k]][k];
        }
    }
}
int jump (int node, int k) {
    for (int i = 0; i < MAXK; i ++)
        if ((1 << i) & k)
            node = parents_2k[node][i];
    return node;
}
int lca (int a, int b) {
    if (depth[a] > depth[b]) swap(a, b);

    b = jump(b, depth[b] - depth[a]);

    if (a == b) return a;

    for (int i = MAXK - 1; i >= 0; i --) {
        if (parents_2k[a][i] == parents_2k[b][i]) continue ;

        a = parents_2k[a][i];
        b = parents_2k[b][i];
    }

    return parents[a];
}
int dist (int a, int b) {
    int l = lca(a, b);
    return depth[a] + depth[b] - 2 * depth[l];
}

idata height;
idata antiheight;

signed main () {
    cin >> N;

    height.resize(N); antiheight.resize(N);
    for (int i = 0; i < N; i ++) {
        cin >> height[i]; height[i] --;
        antiheight[height[i]] = i;
    }

    roads.resize(N);
    for (int i = 1; i < N; i ++) {
        int a, b;
        cin >> a >> b;
        a --; b --;

        roads[a].push_back(b);
        roads[b].push_back(a);
    }

    depth  .resize(N);
    parents.resize(N);
    parents_2k.resize(N, idata(MAXK, -1));
    dfs(0, -1, 0);

    init_lca();

    idata dp(N);

    UFD ufd(N);

    for (int i = 0; i < N; i ++) {
        int pos = antiheight[i];
        int mdp = 0;

        for (int next : roads[pos]) {
            if (height[next] > i) continue ;

            int local = ufd.boss(height[next]);
            int ldp   = dp [antiheight[local]] + dist(antiheight[local], pos);
            mdp = max(ldp, mdp);
            ufd.merge(i, height[next]);
        }

        dp[pos] = mdp;
    }

    cout << dp[antiheight[N - 1]] << endl;
}
#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...