Cod sursa(job #611283)

Utilizator SpiderManSimoiu Robert SpiderMan Data 31 august 2011 17:11:18
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.44 kb
# include <algorithm>
# include <cstdio>
# include <vector>
using namespace std;

const char *FIN = "heavypath.in", *FOU = "heavypath.out";
const int MAX = 100005;

vector <int> G[MAX], L[MAX];
int N, M, v[MAX], lev[MAX], levL[MAX], T[MAX], big[MAX], path[MAX], lant[MAX], dp[MAX], ai[MAX << 2];
bool viz[MAX];

void dfs (int nod) {
    int leaf = 1, most = -1;
    viz[nod] = dp[nod] = 1;
    for (vector <int> :: iterator it = G[nod].begin (); it != G[nod].end (); ++it) {
        if (viz[*it] == 0) {
            lev[*it] = lev[nod] + 1, dfs (*it), leaf = 0;
            dp[nod] += dp[*it], most = (most == -1 || dp[most] < dp[*it]) ? *it : most;
        }
    }
    if (leaf) {
        big[lant[nod] = ++big[0]] = 1;
        L[big[0]].push_back (nod);
        return ;
    }
    ++big[lant[nod] = lant[most]], L[lant[nod]].push_back (nod);
    for (vector <int> :: iterator it = G[nod].begin (); it != G[nod].end (); ++it) {
        if (*it != most && lev[nod] <= lev[*it]) {
            T[lant[*it]] = nod, levL[lant[*it]] = lev[nod];
        }
    }
}

inline int add (int a, int b) {
    return a + b;
}

void buildtree (int nod, int st, int dr, int i, int aux) {
    if (st == dr) {
        ai[add (nod, aux)] = v[L[i][st - 1]];
        return ;
    }
    int mij = st + dr >> 1;
    buildtree (nod << 1, st, mij, i, aux);
    buildtree (nod << 1 | 1, mij + 1, dr, i, aux);
    ai[add (nod, aux)] = max (ai[add (nod << 1, aux)], ai[add (nod << 1 | 1, aux)]);
}

void update (int nod, int st, int dr, int poz, int val, int aux) {
    if (st == dr) {
        ai[add (nod, aux)] = val;
        return ;
    }
    int mij = st + dr >> 1;
    if (poz <= mij)
        update (nod << 1, st, mij, poz, val, aux);
    else
        update (nod << 1 | 1, mij + 1, dr, poz, val, aux);
    ai[add (nod, aux)] = max (ai[add (nod << 1, aux)], ai[add (nod << 1 | 1, aux)]);
}

int query (int nod, int st, int dr, int s1, int s2, int aux) {
    if (s1 <= st && dr <= s2) {
        return ai[add (nod, aux)];
    }
    int mij = st + dr >> 1;
    return max (s1 <= mij ? query (nod << 1, st, mij, s1, s2, aux) : 0, mij < s2 ? query ((nod << 1) + 1, mij + 1, dr, s1, s2, aux) : 0);
}


int main (void) {
    freopen (FIN, "r", stdin);
    freopen (FOU, "w", stdout);

    scanf ("%d %d", &N, &M);
    for (int i = 1; i <= N; ++i)
        scanf ("%d", v + i);
    for (int i = 1, x, y; i < N; ++i) {
        scanf ("%d %d", &x, &y);
        G[x].push_back (y);
        G[y].push_back (x);
    }
    dfs (lev[1] = 1);
    for (int i = 1; i <= big[0]; ++i) {
        reverse (L[i].begin (), L[i].end ());
        buildtree (1, 1, big[i], i, path[i] = (i != 1 ? path[i - 1] + (big[i - 1] << 2) : 0));
    }
    for (int i = 1, z, x, y; i <= M; ++i) {
        scanf ("%d %d %d", &z, &x, &y);
        if (z) {
            for (int sol = 0; ; x = T[lant[x]]) {
                if (lant[x] == lant[y]) {
                    if (lev[x] > lev[y]) swap (x, y);
                    printf ("%d\n", max (sol, query (1, 1, big[lant[x]], lev[x] - levL[lant[x]], lev[y] - levL[lant[y]], path[lant[x]])));
                    break;
                }
                if (levL[lant[x]] < levL[lant[y]]) swap (x, y);
                sol = max (sol, query (1, 1, big[lant[x]], 1, lev[x] - levL[lant[x]], path[lant[x]]));
            }
        } else {
            update (1, 1, big[lant[x]], lev[x] - levL[lant[x]], y, path[lant[x]]);
        }
    }
}