Cod sursa(job #3246082)

Utilizator alexdumitruAlexandru Dumitru alexdumitru Data 1 octombrie 2024 19:59:53
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.46 kb
#include <fstream>
#include <vector>
#include <algorithm>

std::ifstream fin("heavypath.in");
std::ofstream fout("heavypath.out");

const int MAX_N = 100000;
const int MAX_M = 100000;

int n, m;
int a[MAX_N];
std::vector<int> g[MAX_N];
int w[MAX_N], lvl[MAX_N], father[MAX_N];
int in[MAX_N], order[MAX_N];
int id[MAX_N], nxt[MAX_N];

struct query {
    int t, x, y, ans;
} queries[MAX_M];

void read() {
    fin >> n >> m;
    for (int i = 0; i < n; i++) {
        fin >> a[i];
    }
    for (int i = 1; i < n; i++) {
        int u, v;
        fin >> u >> v;
        u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    for (int i = 0; i < m; i++) {
        fin >> queries[i].t >> queries[i].x >> queries[i].y;
        queries[i].x--;
        if (queries[i].t == 1) queries[i].y--;
    }
}

void dfs_init(int node) {
    w[node] = 1;
    for (int & son : g[node]) {
        g[son].erase(std::find(g[son].begin(), g[son].end(), node));
        lvl[son] = lvl[node] + 1;
        father[son] = node;
        dfs_init(son);
        w[node] += w[son];
        if (w[son] > w[g[node][0]])
            std::swap(son, g[node][0]);
    }
}

int nr_lanturi = 1;
int cnt = 0;

void dfs_hld(int node) {
    in[node] = cnt;
    order[cnt++] = node;
    for (int son : g[node]) {
        id[son] = (son == g[node][0] ? id[node] : nr_lanturi++);
        nxt[son] = (son == g[node][0] ? nxt[node] : son);
        dfs_hld(son);
    }
}

namespace AINT {
    int aint[4 * MAX_N];

    void build(int node, int l, int r) {
        if (l == r)
            return void(aint[node] = a[order[l]]);
        int mid = (l + r) / 2;
        build(node * 2 + 1, l, mid);
        build(node * 2 + 2, mid + 1, r);
        aint[node] = std::max(aint[node * 2 + 1], aint[node * 2 + 2]);
    }

    void update(int node, int l, int r, int pos) {
        if (l == r)
            return void(aint[node] = a[order[l]]);
        int mid = (l + r) / 2;
        if (pos <= mid)
            update(node * 2 + 1, l, mid, pos);
        else update(node * 2 + 2, mid + 1, r, pos);
        aint[node] = std::max(aint[node * 2 + 1], aint[node * 2 + 2]);
    }

    int query(int node, int l, int r, int ql, int qr) {
        if (ql <= l && r <= qr)
            return aint[node];
        int mid = (l + r) / 2;
        if (ql <= mid && mid < qr)
            return std::max(query(node * 2 + 1, l, mid, ql, qr), query(node * 2 + 2, mid + 1, r, ql, qr));
        if (ql <= mid)
            return query(node * 2 + 1, l, mid, ql, qr);
        return query(node * 2 + 2, mid + 1, r, ql, qr);
    }
}

int query(int x, int y) {
    int ans = 0;
    while (id[x] != id[y]) {
        if (lvl[nxt[x]] < lvl[nxt[y]]) std::swap(x, y);
        ans = std::max(ans, AINT::query(0, 0, n - 1, in[nxt[x]], in[x]));
        x = father[nxt[x]];
    }
    if (lvl[x] > lvl[y]) std::swap(x, y);
    ans = std::max(ans, AINT::query(0, 0, n - 1, in[x], in[y]));
    return ans;
}



void solve() {
    dfs_init(0);
    dfs_hld(0);
    AINT::build(0, 0, n - 1);

    for (auto & [t, x, y, ans]: queries) {
        if (t == 0) {
            a[x] = y;
            AINT::update(0, 0, n - 1, in[x]);
        } else {
            ans = query(x, y);
        }
    }
}

void write() {
    for (auto [t, x, y, ans] : queries) {
        if (t == 1)
            fout << ans << '\n';
    }
}

int main() {
    read();
    solve();
    write();
    return 0;
}