Cod sursa(job #1811823)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 21 noiembrie 2016 17:14:55
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include <bits/stdc++.h>

#define leftSon (node << 1)
#define rightSon ((node << 1) | 1)

using namespace std;

const int nmax = 1e5 + 10;

int n, m, v[nmax]; vector < int > g[nmax];
int *aint[nmax];

int lvl[nmax], dad[nmax], w[nmax], dim[nmax];
int nrc, chain[nmax], pos[nmax]; vector < int > arr[nmax];

void input() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &v[i]);
    for (int i = 1; i < n; ++i) {
        int x, y;
        scanf("%d %d", &x, &y);

        g[x].push_back(y);
        g[y].push_back(x);
    }
}


void build(int idx, int node, int left, int right) {
    if (left == right) {
        aint[idx][node] = v[arr[idx][left-1]];
        return;
    }

    int mid = (left + right) >> 1;
    build(idx, leftSon, left, mid);
    build(idx, rightSon, mid + 1, right);

    aint[idx][node] = max(aint[idx][leftSon], aint[idx][rightSon]);
}

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

    int mid = (left + right) >> 1;

    if (pos <= mid) update(idx, leftSon, left, mid, pos, val);
    else update(idx, rightSon, mid + 1, right, pos, val);

    aint[idx][node] = max(aint[idx][leftSon], aint[idx][rightSon]);
}

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

    int mid = (left + right) >> 1;

    int ret = -1;
    if (lq <= mid) ret = max(ret, query(idx, leftSon, left, mid, lq, rq));
    if (mid < rq) ret = max(ret, query(idx, rightSon, mid + 1, right, lq, rq));

    return ret;
}


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

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

int get_biggest(int node) {
    int ret = 0;
    for (auto &it : g[node]) {
        if (it == dad[node]) continue;
        if (!ret || w[ret] < w[it])
            ret = it;
    }
    return ret;
}

void chains(int node) {
    chain[node] = nrc;
    arr[nrc].push_back(node);
    pos[node] = ++dim[nrc];

    int to = get_biggest(node);
    if (to) chains(to);

    for (auto &it : g[node]) {
        if (it == dad[node] || it == to)
            continue;

        nrc++;
        chains(it);
    }
}

void build_hpd() {
    dfs(1);
    nrc = 1; chains(1);
    for (int i = 1; i <= nrc; ++i) {
        aint[i] = new int [dim[i]<<2];
        build(i, 1, 1, dim[i]);
    }
}

int go(int x, int y) {
    if (chain[x] == chain[y]) {
        if (pos[x] > pos[y]) swap(x, y);
        return query(chain[x], 1, 1, dim[chain[x]], pos[x], pos[y]);
    }

    int up_x = arr[chain[x]][0]; int up_y = arr[chain[y]][0];
    if (lvl[up_x] < lvl[up_y]) swap(x, y);

    return max(go(dad[arr[chain[x]][0]], y), query(chain[x], 1, 1, dim[chain[x]], 1, pos[x]));
}

void solve_queries() {
    for ( ; m ; --m) {
        int op, x, y;
        scanf("%d %d %d", &op, &x, &y);

        if (op == 0) update(chain[x], 1, 1, dim[chain[x]], pos[x], y);
        else printf("%d\n", go(x, y));
    }
}

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

    input();
    build_hpd();
    solve_queries();

    return 0;
}