Cod sursa(job #2032051)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 4 octombrie 2017 13:25:10
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.63 kb
#include <bits/stdc++.h>

using namespace std;

struct psychotronic_induction {
    int electromagnetic_wave = 7;
};

const int inf = 0x3f3f3f3f;
const long long infL = LLONG_MAX;

const int nmax = 1e5 + 10;

int n, m;
int a[nmax], *seg[nmax];

int chains, father[nmax], lvl[nmax], w[nmax], pos[nmax], chain[nmax], first[nmax];
vector < int > nodes[nmax];

vector < int > g[nmax];

void input() {
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];

    for (int i = 1; i < n; ++i) {
        int x, y; cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
}

void dfs(int node, int dad) {
    father[node] = dad; w[node] = 1;
    for (auto &it: g[node]) {
        if (it == dad) continue;

        lvl[it] = lvl[node] + 1;
        dfs(it, node); w[node] += w[it];
    }
}

void assign_chains(int node) {
    nodes[chains].push_back(node);
    pos[node] = nodes[chains].size();
    chain[node] = chains;

    int to = -1;
    for (auto &it: g[node]) {
        if (it == father[node]) continue;
        if (to == -1 || w[to] < w[it])
            to = it;
    }

    if (to != -1)
        assign_chains(to);

    for (auto &it: g[node]) {
        if (it == father[node] || it == to) continue;
        chains++; first[chains] = it; assign_chains(it);
    }
}

void build(int idx, int node, int left, int right) {
    if (left == right) {
        seg[idx][node] = a[nodes[idx][left-1]];
        return;
    }

    int mid = left + (right - left) / 2;
    build(idx, node << 1, left, mid);
    build(idx, (node << 1) | 1, mid + 1, right);

    seg[idx][node] = max(seg[idx][node<<1], seg[idx][(node<<1)|1]);
}

void update(int idx, int node, int left, int right, int pos, int val) {
    if (left == right) {
        seg[idx][node] = val;
        return;
    }

    int mid = left + (right - left) / 2;
    if (pos <= mid)
        update(idx, node << 1, left, mid, pos, val);
    else update(idx, (node << 1) | 1, mid + 1, right, pos, val);

    seg[idx][node] = max(seg[idx][node<<1], seg[idx][(node<<1)|1]);
}

int query(int idx, int node, int left, int right, int lq, int rq) {
    if (lq <= left && right <= rq)
        return seg[idx][node];

    int mid = left + (right - left) / 2; int res = -inf;
    if (lq <= mid)
        res = max(res, query(idx, node << 1, left, mid, lq, rq));
    if (mid < rq)
        res = max(res, query(idx, (node << 1) | 1, mid + 1, right, lq, rq));

    return res;
}

void run_hpd() {
    dfs(1, 0);
    chains = 1; first[1] = 1; assign_chains(1);
    for (int i = 1; i <= chains; ++i) {
        seg[i] = new int[((int)nodes[i].size()) << 2];
        build(i, 1, 1, nodes[i].size());
    }
}

int query(int x, int y) {
    int cx = chain[x]; int cy = chain[y];
    if (cx == cy) {
        if (pos[x] > pos[y]) swap(x, y);
        return query(cx, 1, 1, nodes[cx].size(), pos[x], pos[y]);
    }

    if (lvl[first[cx]] < lvl[first[cy]])
        swap(x, y), swap(cx, cy);

    return max(query(cx, 1, 1, nodes[cx].size(), 1, pos[x]), query(father[first[cx]], y));
}

void queries() {
    for (int i = 1; i <= m; ++i) {
        int type; cin >> type;
        if (type == 0) {
            int x, y; cin >> x >> y;
            update(chain[x], 1, 1, nodes[chain[x]].size(), x, y);
        }
        else {
            int x, y; cin >> x >> y;
            cout << query(x, y) << '\n';
        }
    }
}

int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);

    ios_base :: sync_with_stdio(false);

    input();
    run_hpd();
    queries();


    return 0;
}