Cod sursa(job #1969033)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 18 aprilie 2017 10:43:12
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.31 kb
#include <bits/stdc++.h>

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

using namespace std;

const int nmax = 1e5 + 10;
const int inf = 2e9 + 10;

int n, m, a[nmax];
int *seg[nmax];
vector < int > g[nmax];

int w[nmax], lvl[nmax], father[nmax];

int chains, label[nmax], whr[nmax], sz[nmax];
vector < int > chain[nmax];

void input() {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &a[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 dfs(int node, int dad, int level) {
    w[node] = 1; lvl[node] = level; father[node] = dad;
    for (auto &it: g[node]) {
        if (it == dad) continue;
        dfs(it, node, level + 1); w[node] += w[it];
    }
}

void assign_chain(int node, int dad, int idx) {
    label[node] = idx; whr[node] = ++sz[idx];
    chain[idx].push_back(node);

    int to = 0;
    for (auto &it: g[node]) {
        if (it == dad) continue;
        if (w[it] > w[to]) to = it;
    }

    if (to) assign_chain(to, node, idx);
    for (auto &it: g[node]) {
        if (it == dad || it == to) continue;
        assign_chain(it, node, ++chains);
    }
}

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

    int mid = left + (right - left) / 2;
    build(idx, leftSon, left, mid);
    build(idx, rightSon, mid + 1, right);

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

void build_seg() {
    for (int i = 1; i <= chains; ++i) {
        seg[i] = new int [sz[i] << 2];
        build(i, 1, 1, sz[i]);
    }
}

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, leftSon, left, mid, pos, val);
    else update(idx, rightSon, mid + 1, right, pos, val);

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

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, leftSon, left, mid, lq, rq));
    if (mid < rq)
        res = max(res, query(idx, rightSon, mid + 1, right, lq, rq));

    return res;
}

int do_query(int x, int y) {
    if (label[x] == label[y]) {
        if (whr[x] > whr[y]) swap(x, y);
        return query(label[x], 1, 1, sz[label[x]], whr[x], whr[y]);
    }

    if (lvl[x] < lvl[y]) swap(x, y);
    int curr = query(label[x], 1, 1, sz[label[x]], 1, whr[x]);

    return max(curr, do_query(father[chain[label[x]][0]], y));
}

void output() {
    for (int i = 1; i <= m; ++i) {
        int type, x, y;
        scanf("%d %d %d", &type, &x, &y);

        if (type == 0)
            update(label[x], 1, 1, sz[label[x]], whr[x], y);
        else printf("%d\n", do_query(x, y));
    }
}

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

    input();
    dfs(1, 1, 1);
    assign_chain(1, 0, ++chains);
    build_seg();
    output();

    return 0;
}