Cod sursa(job #1963347)

Utilizator TibixbAndrei Tiberiu Tibixb Data 12 aprilie 2017 14:20:59
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.12 kb
#include<fstream>
#include<vector>
#include<algorithm>
#define NMAX 100005
using namespace std;
vector<int> G[NMAX];
vector<int> p[NMAX];
int A[4 * NMAX];
int n, m, x, y, op, qs, sol_path;
int np;
int value[NMAX];
int wg[NMAX], niv[NMAX], ps[NMAX];
int wp[NMAX], pf[NMAX], pfniv[NMAX];
int dcj[NMAX];
bool u[NMAX];
ifstream _cin("heavypath.in");
ofstream _cout("heavypath.out");

void update(int st, int dr, int nod, int poz, int upd, int decal)
{
    if(st == dr)
    {
        A[nod + decal] = upd;
        return;
    }

    int mij = st + (dr - st) / 2;

    if(poz <=  mij)
    {
        update(st, mij, 2 * nod, poz, upd, decal);
    }else
    {
        update(mij + 1, dr, 2 * nod + 1, poz, upd, decal);
    }

    A[nod + decal] = max(A[2 * nod + decal], A[2 * nod + 1 + decal]);
}

void build(int st, int dr, int nod, int path, int decal)
{
    if(st == dr)
    {
        A[nod + decal] = value[p[path][st - 1]];
        return;
    }

    int mij = st + (dr - st) / 2;

    build(st, mij, 2 * nod, path, decal);

    build(mij + 1, dr, 2 * nod + 1, path, decal);

    A[nod + decal] = max(A[2 * nod + decal], A[2 * nod + 1 + decal]);
}

void query(int st, int dr, int nod, int a, int b, int decal)
{
    if(a <= st && dr <= b)
    {
        qs = max(A[nod + decal], qs);
        return;
    }

    int mij = st + (dr - st) / 2;

    if(a <=  mij)
    {
        query(st, mij, 2 * nod, a, b, decal);
    }
    if(b > mij)
    {
        query(mij + 1, dr, 2 * nod + 1, a, b, decal);
    }
}

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

    wg[nod] = 1;

    int hn = -1, frunza = 1;
    for(int i = 0; i < G[nod].size(); i++)
    {
        int fiu = G[nod][i];
        if(u[fiu] == 0)
        {
            niv[fiu] = 1 + niv[nod];
            dfs(fiu);

            frunza = 0;

            wg[nod] += wg[fiu];

            if(hn == -1)
            {
                hn = fiu;
            }else
            {
                if(wg[fiu] > wg[hn])
                {
                    hn = fiu;
                }
            }
        }
    }

    if(frunza)
    {
        np++;
        wp[nod] = np;
        ps[np] = 1;
        p[np].push_back(nod);
        return;
    }

    wp[nod] = wp[hn];
    ps[wp[nod]]++;
    p[wp[nod]].push_back(nod);

    for(int i = 0; i < G[nod].size(); i++)
    {
        int fiu = G[nod][i];
        if(wp[fiu] != wp[nod] && niv[fiu] > niv[nod])
        {
            pf[wp[fiu]] = nod;
            pfniv[wp[fiu]] = niv[nod];
        }
    }
}

void make_paths()
{
    niv[1] = 1;
    dfs(1);

    for(int i = 1; i <= np; i++)
    {
        reverse(p[i].begin(), p[i].end());
    }

    for(int i = 1; i < np; i++)
    {
        dcj[i + 1] = 4 * p[i].size() + dcj[i];
        build(1, p[i].size(), 1, i, dcj[i]);
    }
    build(1, p[np].size(), 1, np, dcj[np]);
}

int main()
{
    _cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        _cin >> value[i];
    }

    for(int i = 1; i < n; i++)
    {
        _cin >> x >> y;
        G[x].push_back(y);
        G[y].push_back(x);
    }

    make_paths();

    for(int i = 1; i <= m; i++)
    {
        _cin >> op >> x >> y;
        if(op == 0)
        {
            update(1, ps[wp[x]], 1, niv[x] - pfniv[wp[x]], y, dcj[wp[x]]);
        }else
        {
            sol_path = 0;

            while(wp[x] != wp[y])
            {
                if(pfniv[wp[x]] < pfniv[wp[y]])
                {
                    swap(x, y);
                }
                qs = 0;
                query(1, ps[wp[x]], 1, 1, niv[x] - pfniv[wp[x]], dcj[wp[x]]);
                x = pf[wp[x]];

                sol_path = max(qs, sol_path);
            }
            if(niv[x] < niv[y])
            {
                swap(x, y);
            }
            qs = 0;
            query(1, ps[wp[x]], 1, niv[y] - pfniv[wp[y]], niv[x] - pfniv[wp[x]], dcj[wp[x]]);
            sol_path = max(qs, sol_path);

            _cout << sol_path << "\n";
        }
    }
    return 0;
}