Cod sursa(job #978815)

Utilizator FlameingoAiordachioaei Marius Flameingo Data 29 iulie 2013 18:56:58
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.56 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 << 2], d[NMAX], L, k, _l, _r, rv, rh;
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]) {
            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 (aint[nod + d[k]])
        printf (":))");
    if (rh < nod)
        rh = nod;
    if (l == r) {
        aint[nod + d[k]] = 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[nod + d[k]] = max (aint[(nod << 1) + d[k]], aint[(nod << 1) + 1 + d[k]]);

}

void build () {

    DFS (1);
    int i;
    for (k = 1; k <= L; ++k) {
        rh = 0;
        i = C[k].size ();
        reverse (C[k].begin (), C[k].end ());
        AINT_build (0, i - 1, 1);
        d[k + 1] = rh + d[k];
    }

}

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[nod + d[k]] > rv)
            rv = aint[nod + d[k]];
        return;
    }
    int m = l + r >> 1;
    AINT_query (l, m, nod * 2);
    AINT_query (m + 1, r, nod * 2 + 1);

}

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

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

}

int main () {

    freopen ("heavypath.in", "r", stdin);
    freopen ("heavypath.out", "w", stdout);
    int i, N, M, a, b, mt, 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);

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