Cod sursa(job #1925711)

Utilizator Theodor1000Cristea Theodor Stefan Theodor1000 Data 13 martie 2017 16:49:18
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.7 kb
#include <cstdio>
#include <algorithm>
#include <vector>

using namespace std;

int n, m;
int v[100010], aint[200010], niv[100010], wei[100010], l[100010], tal[100010], nil[100010], st[100010], poz[100010], nl = 0;
vector <int> g[100010], lant[100010];

inline void dfs (int nod, int tata)
{
    niv[nod] = niv[tata] + 1;
    wei[nod] = 1;

    int ww = 0;
    for (auto &it : g[nod])
    {
        if (it == tata) continue;
        dfs (it, nod);

        wei[nod] += wei[it];

        if (wei[it] > wei[ww])
            ww = it;
    }

    if (!ww)
    {
        lant[++nl].push_back (nod);
        l[nod] = nl;

        tal[nl] = tata;
        nil[nl] = niv[nod];

        return;
    }

    int la = l[nod] = l[ww];
    lant[la].push_back (nod);

    tal[la] = tata;
    nil[la] = niv[nod];
}

inline void build ()
{
    for (int i = n - 1; i; --i)
        aint[i] = max (aint[i << 1], aint[i << 1 | 1]);
}

inline void update (int poz, int val)
{
    aint[poz += n - 1] = val;
    for (poz >>= 1; poz; poz >>= 1)
        aint[poz] = max (aint[poz << 1], aint[poz << 1 | 1]);
}

inline int querry (int st, int dr)
{
    int ma = 0;
    for (st += n - 1, dr += n; st < dr; st >>= 1, dr >>= 1)
    {
        if (st & 1) ma = max (ma, aint[st++]);
        if (dr & 1) ma = max (ma, aint[--dr]);
    }

    return ma;
}

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

    scanf ("%d %d", &n, &m);

    for (int i = 1; i <= n; ++i)
        scanf ("%d", &v[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);
    }

    dfs (1, 0);

    st[0] = 1;
    for (int i = 1; i <= nl; ++i)
    {
        reverse (lant[i].begin (), lant[i].end ());

        st[i] = st[i - 1] + lant[i - 1].size ();
        int dr = st[i] + lant[i].size () - 1;

        for (int j = st[i]; j <= dr; ++j)
            aint[(j - 1) + n] = v[lant[i][j - st[i]]],
            poz[lant[i][j - st[i]]] = j;
    }

    build ();

    for (; m; --m)
    {
        int op, a, b;
        scanf ("%d %d %d", &op, &a, &b);

        if (!op)
        {
            update (poz[a], b);
            continue;
        }

        int la = l[a], lb = l[b], ma = 0;
        for (; la != lb;)
        {
            if (nil[la] < nil[lb]) swap (la, lb), swap (a, b);

            ma = max (ma, querry (st[la], poz[a]));

            a = tal[la];
            la = l[a];
        }

        if (niv[a] > niv[b]) swap (a, b);

        ma = max (ma, querry (poz[a], poz[b]));
        printf ("%d\n", ma);
    }

    return 0;
}