Cod sursa(job #1148782)

Utilizator Ionut228Ionut Calofir Ionut228 Data 21 martie 2014 09:04:39
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.25 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

int N, M, type, x, y;
int sol, nL, maxim;
int value[100001];
int aint[400004];
int nrNod[100001], lvl[100001], l[100001], lFather[100001], lLvl[100001], lDim[100001], lPos[100001];
vector<int> V[100001], path[100001];
bool used[100001];

void dfs(int nod)
{
    used[nod] = true;
    nrNod[nod] = 1;

    int lastNod = -1, leaf = 1;

    for (vector<int>::iterator it = V[nod].begin(); it != V[nod].end(); ++it)
    {
        if (!used[*it])
        {
            leaf = 0;
            lvl[*it] = lvl[nod] + 1;

            dfs(*it);

            nrNod[nod] += nrNod[*it];

            if (lastNod == -1)
                lastNod = *it;
            else if (nrNod[lastNod] < nrNod[*it])
                lastNod = *it;
        }
    }

    if (leaf)
    {
        ++nL;
        l[nod] = nL;
        lDim[nL] = 1;
        path[nL].push_back(nod);
        return;
    }

    l[nod] = l[lastNod];
    ++lDim[l[lastNod]];
    path[l[lastNod]].push_back(nod);

    for (vector<int>::iterator it = V[nod].begin(); it != V[nod].end(); ++it)
    {
        if (*it == lastNod || lvl[*it] < lvl[nod])
            continue;

        lFather[l[*it]] = nod;
        lLvl[l[*it]] = lvl[nod];
    }
}

void build(int nod, int lt, int rt, int decalaj, int lant)
{
    if (lt == rt)
    {
        aint[nod + decalaj] = value[path[lant][lt - 1]];
        return;
    }

    int mid = (lt + rt) >> 1;

    build(nod * 2, lt, mid, decalaj, lant);
    build(nod * 2 + 1, mid + 1, rt, decalaj, lant);

    aint[nod + decalaj] = max(aint[nod * 2 + decalaj], aint[nod * 2 + 1 + decalaj]);
}

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

    for(int i = 1; i <= nL; ++i)
    {
        reverse(path[i].begin(), path[i].end());

        if(i > 1)
            lPos[i] = lPos[i-1] + lDim[i-1] * 4;

        build(1, 1, lDim[i], lPos[i], i);
    }
}

void update(int nod, int lt, int rt, int pos, int val, int decalaj)
{
    if (lt == rt)
    {
        aint[nod + decalaj] = val;
        return;
    }

    int mid = (lt + rt) >> 1;

    if (pos <= mid)
        update(nod * 2, lt, mid, pos, val, decalaj);
    else
        update(nod * 2 + 1, mid + 1, rt, pos, val, decalaj);

    aint[nod + decalaj] = max(aint[nod * 2 + decalaj], aint[nod * 2 + 1 + decalaj]);
}

void query(int nod, int lt, int rt, int start, int finish, int decalaj)
{
    if (start <= lt && rt <= finish)
    {
        if (aint[nod] > maxim)
            maxim = aint[nod];
        return;
    }

    int mid = (lt + rt) >> 1;

    if (start <= mid)
        query(nod * 2, lt, mid, start, finish, decalaj);
    if (mid < finish)
        query(nod * 2 + 1, mid + 1, rt, start, finish, decalaj);
}

void solve()
{
    for (int i = 1; i <= M; ++i)
    {
        fin >> type >> x >> y;
        if (type == 0)
            update(1, 1, lDim[l[x]], lvl[x] - lLvl[l[x]], y, lPos[l[x]]);
        else
        {
            sol = 0;
            bool ok = true;
            while(ok)
            {
                if (l[x] == l[y])
                {
                    if (lvl[x] > lvl[y])
                        swap(x, y);
                    query(1, 1, lDim[l[x]], lvl[x] - lLvl[l[x]], lvl[y] - lLvl[l[y]], lPos[l[x]]);
                    sol = max(sol, maxim);
                    ok = false;
                    break;
                }

                if (lLvl[l[x]] < lLvl[l[y]])
                    swap(x, y);

            }
        }
    }
}

int main()
{
    fin >> N >> M;
    for (int i = 1; i <= N; ++i)
        fin >> value[i];
    for (int i = 1, nod1, nod2; i <= N - 1; ++i)
    {
        fin >> nod1 >> nod2;
        V[nod1].push_back(nod2);
        V[nod2].push_back(nod1);
    }

    make_paths();

    /*
    for (int i = 1; i <= 100; ++i)
        fout << aint[i] << ' ';
    fout << '\n';

    fout << nL << '\n';
    for (int i = 1; i <= nL; ++i)
    {
        for (vector<int>::iterator it = path[i].begin(); it != path[i].end(); ++it)
            fout << *it << ' ';
        fout << '\n';
    }
    */

    fin.close();
    fout.close();
    return 0;
}