Cod sursa(job #2461072)

Utilizator bogdanvladmihaiBogdan Vlad-Mihai bogdanvladmihai Data 24 septembrie 2019 20:57:18
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.59 kb
#include <bits/stdc++.h>

using namespace std;

const int MAX_V = 100005;

int n, m;

int nodes[MAX_V];
int siz[MAX_V];
int parrent[MAX_V];
int head[MAX_V];
int level[MAX_V];
int index[MAX_V];

int tree[MAX_V * 4];

vector < int > G[MAX_V];
vector < int > dfsOrder;

int querySegTree(int node, int lo, int ri, int st, int en) {
    if (lo > ri) {
        return INT_MIN;
    }
    if (st <= lo && ri <= en) {
        return tree[node];
    }
    int mid = (lo + ri) / 2;
    if (st > mid) {
        return querySegTree(2 * node + 1, mid + 1, ri, st, en);
    } else if (en <= mid) {
        return querySegTree(2 * node, lo, mid, st, en);
    } else {
        return max(querySegTree(2 * node + 1, mid + 1, ri, st, en), querySegTree(2 * node, lo, mid, st, en));
    }
}

void updateSegTree(int node, int lo, int ri, int pos, int value) {
    if (lo > ri) {
        return;
    }
    if (lo == ri) {
        tree[node] = value;
        return;
    }
    int mid = (lo + ri) / 2;
    if (pos <= mid) {
        updateSegTree(2 * node, lo, mid, pos, value);
    } else {
        updateSegTree(2 * node + 1, mid + 1, ri, pos, value);
    }
    tree[node] = max(tree[2 * node], tree[2 * node + 1]);
}

void dfs(int u, int dad) {
    siz[u] = 1;
    parrent[u] = dad;
    level[u] = level[dad] + 1;
    for (int v : G[u]) {
        if (v != dad) {
            dfs(v, u);
            siz[u] += siz[v];
        }
    }
}

void heavyDfs(int u) {
    index[u] = int(dfsOrder.size()) + 1;
    dfsOrder.push_back(u);
    if (int(G[u].size()) == 0) {
        return;
    }
    int heavySon = G[u][0];
    if (int(G[u].size()) == 1 && int(G[u][0]) == parrent[u]) {
        return;
    } else {
        if (int(G[u].size()) >= 2 && G[u][0] == parrent[u]) {
            heavySon = G[u][1];
        }
    }
    for (int v : G[u]) {
        if (siz[heavySon] < siz[v] && v != heavySon && v != parrent[u]) {
            heavySon = v;
        }
    }
    head[heavySon] = head[u];
    heavyDfs(heavySon);
    for (int v : G[u]) {
        if (v != heavySon && v != parrent[u]) {
            heavyDfs(v);
        }
    }
}

void pp(int& u, int &v) {
    if (index[u] > index[v]) {
        swap(u, v);
    }
    return;
}

void update(int node, int val) {
    updateSegTree(1, 1, n, index[node], val);
    return;
}

int query(int u, int v) {
    if (head[u] == head[v]) {
        pp(u, v);
        return querySegTree(1, 1, n, index[u], index[v]);
    }
    int ans = 0;
    if (level[parrent[head[u]]] > level[parrent[head[v]]]) {
        ans = querySegTree(1, 1, n, min(index[u], index[head[u]]), max(index[u], index[head[u]]));
        u = parrent[head[u]];
    } else {
        ans = querySegTree(1, 1, n, min(index[v], index[head[v]]), max(index[v], index[head[v]]));
        v = parrent[head[v]];
    }
    return max(ans, query(u, v));
}

int main() {
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) {
        cin >> nodes[i];
    }
    for (int i = 2; i <= n; ++i) {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= n; ++i) {
        head[i] = i;
    }
    heavyDfs(1);
    for (int i = 1; i <= n; ++i) {
        update(i, nodes[i]);
    }
    while (m --) {
        int t, u, v;
        cin >> t >> u >> v;
        if (t == 0) {
            update(u, v);
        } else if (t == 1) {
            cout << query(u, v) << "\n";
        }
    }
    return 0;
}