Cod sursa(job #1323285)

Utilizator florin.elfusFlorin Elfus florin.elfus Data 20 ianuarie 2015 21:51:21
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.52 kb
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>

using namespace std;

const int kNMAX = 100100;

int val[kNMAX];
vector <int> G[kNMAX];

int subTree[kNMAX], lev[kNMAX];
bool vis[kNMAX];

void dfs(int nod) {
    vis[nod] = 1;
    subTree[nod] = 1;

    vector <int> :: iterator it;
    for (it = G[nod].begin(); it != G[nod].end(); ++it)
        if (!vis[*it]) {
            lev[*it] = lev[nod] + 1;
            dfs(*it);
            subTree[nod] += subTree[*it];
        }
}

int cntLant, lungLant[kNMAX], incLant[kNMAX], tataLant[kNMAX];
int lantNod[kNMAX], pozNod[kNMAX];

vector <int> aint[4 * kNMAX];

void dfs2(int nod, int lant) {
    ++lungLant[lant];
    lantNod[nod] = lant;
    pozNod[nod] = lungLant[lant];
    vis[nod] = 1;

    int bestSub = 0;
    vector <int> :: iterator it;
    for (it = G[nod].begin(); it != G[nod].end(); ++it)
        if (!vis[*it])
            if (subTree[nod] > bestSub)
                bestSub = subTree[nod];
    for (it = G[nod].begin(); it != G[nod].end(); ++it)
        if (!vis[*it] && subTree[*it] == bestSub) {
            dfs2(*it, lant);
            break;
        }
    for (it = G[nod].begin(); it != G[nod].end(); ++it)
        if (!vis[*it]) {
            ++cntLant;
            incLant[cntLant] = *it;
            tataLant[cntLant] = nod;
            dfs2(*it, cntLant);
        }
}

void update(int lant, int nod, int st, int dr, int pos, int val) {
    if (st == dr) {
        aint[lant][st] = val;
        return ;
    }

    int med = (st + dr) / 2;
    if (pos <= med)
        update(lant, nod, st, med, pos, val);
    else
        update(lant, nod, med + 1, dr, pos, val);

    aint[lant][nod] = max(aint[lant][2 * nod], aint[lant][2 * nod + 1]);
}

int query(int lant, int nod, int st, int dr, int qst, int qdr) {
    if (qst > qdr)
        swap(qst, qdr);
    if (st <= qst && qdr <= dr)
        return aint[lant][nod];

    int med = (st + dr) / 2, res = 0;
    if (qst <= med)
        res = query(lant, 2 * nod, st, med, qst, qdr);
    if (med < qdr)
        res = max(res, query(lant, 2 * nod + 1, med + 1, dr, qst, qdr));

    return res;
}

int solve(int nod1, int nod2) {
    int res = 0;
    while (lantNod[nod1] != lantNod[nod2]) {
        if (lev[incLant[nod1]] < lev[incLant[nod2]])
            swap(nod1, nod2);
        res = max(res, query(lantNod[nod1], 1, 1, lungLant[lantNod[nod1]], 1, pozNod[nod1]));
        nod1 = tataLant[nod1];
    }

    res = max(res, query(lantNod[nod1], 1, 1, lungLant[lantNod[nod1]], pozNod[nod1], pozNod[nod2]));
    return res;
}

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

    int n, q;
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= n; ++i)
        scanf("%d", &val[i]);
    for (int i = 1; i < n; ++i) {
        int xx, yy;
        scanf("%d%d", &xx, &yy);
        G[xx].push_back(yy);
        G[yy].push_back(xx);
    }

    dfs(1);
    incLant[++cntLant] = 1;
    memset(vis, 0, sizeof(vis));
    dfs2(1, 1);

    for (int i = 1; i <= cntLant; ++i)
        aint[i].resize(4 * lungLant[i]);
    for (int i = 1; i <= n; ++i)
        update(lantNod[i], 1, 1, lungLant[lantNod[i]], pozNod[i], val[i]);

    for (int i = 1; i <= q; ++i) {
        int type, a, b;
        scanf("%d%d%d", &type, &a, &b);
        if (type == 0)
            update(lantNod[a], 1, 1, lungLant[lant[a]], pozNod[a], b);
        else
            printf("%d\n", solve(a, b));
    }

    return 0;
}