Submission #1340530

#TimeUsernameProblemLanguageResultExecution timeMemory
1340530filipciakojanCat Exercise (JOI23_ho_t4)C++20
100 / 100
352 ms50536 KiB
#include <iostream>
#include <algorithm>
#include <vector>
using ll = long long;

using namespace std;

struct Point {
    int value, depth = -1, number;
    vector<int> neighbours;
};

vector<Point> points;

struct DSU {
    vector<ll> wyniki; // remember to initialize
    vector<int> parent;
    DSU(int n) {
        wyniki.resize(n, 0);
        parent.resize(n);
        for (int i = 0; i < n; i++) {
            parent[i] = i;
        }
    }
    int find(int x) {
        if (parent[x] == x) return x;
        return parent[x] = find(parent[x]);
    }
    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if (x == y) {
            cout << "alr connected?" << endl;
            return;
        }
        if (points[y].value > points[x].value) {
            swap(x, y);
        }
        parent[y] = x;
    }
};

bool compare(int a, int b) {
    return points[a].value < points[b].value;
}


// ===== LCA ADDITION START =====
const int LOG = 20;
vector<vector<int>> up;

void dfs_lca(int v, int p) {
    up[v][0] = p;
    for (int i = 1; i < LOG; i++) {
        up[v][i] = up[up[v][i - 1]][i - 1];
    }
    for (int u : points[v].neighbours) {
        if (u != p) {
            dfs_lca(u, v);
        }
    }
}

void init_lca(int n) {
    up.assign(n, vector<int>(LOG));
    dfs_lca(0, 0);
}

int lca(int a, int b) {
    // Lazy initialization since init_lca is not called in main
    if (up.empty()) {
        init_lca(points.size());
    }

    if (points[a].depth < points[b].depth) swap(a, b);

    int diff = points[a].depth - points[b].depth;
    for (int i = 0; i < LOG; i++) {
        if (diff & (1 << i)) {
            a = up[a][i];
        }
    }

    if (a == b) return a;

    for (int i = LOG - 1; i >= 0; i--) {
        if (up[a][i] != up[b][i]) {
            a = up[a][i];
            b = up[b][i];
        }
    }

    return up[a][0];
}
// ===== LCA ADDITION END =====



int dystans(int a, int b) {
    return points[a].depth + points[b].depth - 2 * points[lca(a, b)].depth;
}

void DFS(int v);

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n;
    cin >> n;
    DSU dsu(n);
    points.resize(n);
    for (int i = 0; i < n; i++) {
        int v;
        cin >> v;
        points[i].value = v;
    }
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        points[a].neighbours.push_back(b);
        points[b].neighbours.push_back(a);
    }
    points[0].depth = 0;
    DFS(0);
    vector<int> order(n);
    for (int i = 0; i < n; i++) {
        order[i] = i;
    }
    sort(order.begin(), order.end(), compare);
    ll wynik = 0;
    for (int i = 0; i < n; i++) {
        //for each vertex
        int p = order[i];
        //cout << "I'm currently in point " << p << " and my value is " << points[p].value << endl;
        //cout << "my neighbours are: \n";
        for (int neighbour : points[p].neighbours) {
            neighbour = dsu.find(neighbour);
            //cout << neighbour << " ";
            // nie robie & reference, wiec moge sie tak bawic
            if (points[neighbour].value > points[p].value) {
                //cout << "jego skipuje" << endl;
                continue;
            }
            //cout << "obliczam wynik" << endl;
            dsu.wyniki[p] = max(dsu.wyniki[p], dystans(p, neighbour) + dsu.wyniki[neighbour]);
            //cout << "policzony wynik to " << dsu.wyniki[p] << endl;
            dsu.unite(p, neighbour);
        }
        //cout << endl;
        wynik = max(wynik, dsu.wyniki[p]);
    }
    cout << wynik << endl;
}
void DFS(int v) {
    for (int neighour : points[v].neighbours) {
        if (points[neighour].depth == -1) {
            points[neighour].depth = points[v].depth + 1;
            DFS(neighour);
        }
    }
}
#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...