Cod sursa(job #978390)

Utilizator FlameingoAiordachioaei Marius Flameingo Data 28 iulie 2013 18:59:08
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.41 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

const int NMAX = 100003;
vector <int> A[NMAX], C[NMAX];
int V[NMAX], n[NMAX], t[NMAX], cl[NMAX], sa[NMAX], *aint[NMAX], L, k, _l, _r, rv;
bool viz[NMAX];

void DFS (const int nod) {

    viz[nod] = 1;
    int mn;
    bool f = 1;
    for (vector <int> :: iterator i = A[nod].begin (); i != A[nod].end (); ++i) {
        if (viz[*i])
            continue;
        n[*i] = n[nod] + 1;
        t[*i] = nod;
        DFS (*i);
        if (f)
            mn = *i,
            f = 0;
        else
            if (sa[*i] > sa[mn])
                mn = *i;
        sa[nod] += sa[*i];
    }

    if (f) {
        ++sa[nod];
        cl[nod] = ++L;
        C[L].push_back (nod);
        return;
    }
    C[cl[mn]].push_back (nod);
    cl[nod] = cl[mn];

}

void AINT_build (const int l, const int r, const int nod) {

    if (l == r) {
        aint[k][nod] = V[C[k][l]];
        return;
    }
    int m = (l + r) >> 1;
    AINT_build (l, m, nod << 1);
    AINT_build (m + 1, r, (nod << 1) + 1);
    aint[k][nod] = max (aint[k][nod << 1], aint[k][(nod << 1) + 1]);

}

void build () {

    for (k = 1; k <= L; ++k) {
        reverse (C[k].begin (), C[k].end ());
        aint[k] = new int[(C[k].size () << 1) + 2];
        AINT_build (0, C[k].size () - 1, 1);
    }

}

void AINT_query (const int l, const int r, const int nod) {

    if (_r < l || _l > r)
        return;
    if (_l <= l && _r >= r) {
        if (aint[k][nod] > rv)
            rv = aint[k][nod];
        return;
    }
    int m = (l + r) >> 1;
    AINT_query (l, m, nod << 1);
    AINT_query (m + 1, r, (nod << 1) + 1);

}

void AINT_update (const int l, const int r, int const nod) {

    if (l == r) {
        aint[k][nod] = _r;
        return;
    }
    int m = (l + r) >> 1;
    if (_l <= m)
        AINT_update (l, m, nod << 1);
    else
        AINT_update (m + 1, r, (nod << 1) + 1);
    aint[k][nod] = max (aint[k][nod << 1], aint[k][(nod << 1) + 1]);

}

int main () {

    freopen ("heavypath.in", "r", stdin);
    freopen ("heavypath.out", "w", stdout);
    int i, N, M, a, b, mt;
    bool w;
    scanf ("%d%d", &N, &M);
    for (i = 1; i <= N; ++i)
        scanf ("%d", &V[i]);
    for (i = 1; i < N; ++i)
        scanf ("%d%d", &a, &b),
        A[a].push_back (b),
        A[b].push_back (a);

    n[1] = 1;
    DFS (1);
    build ();

    while (M--) {
        scanf ("%d%d%d", &w, &a, &b);
        mt = 0;
        if (w) {
            while (cl[a] != cl[b]) {
                if (n[C[cl[a]][0]] < n[C[cl[b]][0]])
                    swap (a, b);
                k = cl[a];
                rv = 0;
                _l = 0;
                _r = n[a] - n[C[cl[a]][0]];
                AINT_query (0, C[k].size () - 1, 1);
                a = t[C[cl[a]][0]];
                if (rv > mt)
                    mt = rv;
            }
            if (n[a] > n[b])
                swap (a, b);
            k = cl[a];
            rv = 0;
            _l = n[a] - n[C[cl[a]][0]];
            _r = n[b] - n[C[cl[b]][0]];
            AINT_query (0, C[k].size () - 1, 1);
            if (rv > mt)
                mt = rv;
            printf ("%d\n", mt);
            continue;
        }
        k = cl[a];
        _l = n[a] - n[C[cl[a]][0]];
        _r = b;
        AINT_update (0, C[k].size () - 1, 1);
    }
}