Cod sursa(job #1856543)

Utilizator EpictetStamatin Cristian Epictet Data 25 ianuarie 2017 00:39:15
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 4.21 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

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

int n, m, nr_l;
int V[100010], W[100010], Level[100010], L[100010];
int L_Tata[100010], L_Level[100010], L_Dim[100010], L_Pos[100010];
int AINT[400010];
bool F[100010];
vector < int > G[100010], Path[100010];

void DFS(int node)
{
    F[node] = true;

    int biggest_chain = -1, leaf = 1;

    for (vector < int > :: iterator it = G[node].begin(); it != G[node].end(); it ++)
    {
        if (!F[*it])
        {
            leaf = 0;
            Level[*it] = Level[node] + 1;

            DFS(*it);

            if (biggest_chain < 0 || W[*it] > W[biggest_chain])
            {
                biggest_chain = *it;
            }
        }
    }

    if (leaf)
    {
        nr_l ++;
        L[node] = nr_l;
        L_Dim[nr_l] = 1;
        Path[nr_l].push_back(node);
    }
    else
    {
        W[node] = W[biggest_chain] + 1;
        L[node] = L[biggest_chain];
        L_Dim[L[node]] += 1;
        Path[L[node]].push_back(node);

        for (vector < int > :: iterator it = G[node].begin(); it != G[node].end(); it ++)
        {
            if (*it != biggest_chain && Level[*it] > Level[node])
            {
                L_Tata[L[*it]] = node;
                L_Level[L[*it]] = Level[node];
            }
        }
    }
}

inline int Maxim(int const &a, int const &b)
{
    if (a > b) return a;
    return b;
}

void Build_Tree(int node, int left, int right, int decalaj, int lant)
{
    if (left == right)
    {
        AINT[node + decalaj] = V[Path[lant][left - 1]];
    }
    else
    {
        int mid = (left + right) / 2;

        Build_Tree(node * 2, left, mid, decalaj, lant);
        Build_Tree(node * 2 + 1, mid + 1, right, decalaj, lant);

        AINT[node + decalaj] = Maxim(AINT[node * 2 + decalaj], AINT[node * 2 + 1 + decalaj]);
    }
}

void Make_Paths()
{
    Level[1] = 1;
    DFS(1);

    for (int i = 1; i <= nr_l; i ++)
    {
        reverse(Path[i].begin(), Path[i].end());
        if (i > 1) L_Pos[i] = L_Pos[i - 1] + L_Dim[i - 1] * 4;
        Build_Tree(1, 1, L_Dim[i], L_Pos[i], i);
    }
}

void Update(int node, int left, int right, int pos, int val, int decalaj)
{
    if (left == right)
    {
        AINT[node + decalaj] = val;
    }
    else
    {
        int mid = (left + right) / 2;

        if (pos <= mid) Update(node * 2, left, mid, pos, val, decalaj);
        else Update(node * 2 + 1, mid + 1, right, pos, val, decalaj);

        AINT[node + decalaj] = Maxim(AINT[node * 2 + decalaj], AINT[node * 2 + 1 + decalaj]);
    }
}

int Query(int node, int left, int right, int a, int b, int decalaj)
{
    if (a <= left && right <= b)
    {
        return AINT[node + decalaj];
    }
    else
    {
        int mid = (left + right) / 2, ret1 = 0, ret2 = 0;
        if (a <= mid) ret1 = Query(node * 2, left, mid, a, b, decalaj);
        if (b > mid) ret2 = Query(node * 2 + 1, mid + 1, right, a, b, decalaj);

        return Maxim(ret1, ret2);
    }
}

int main()
{
    fin >> n >> m;
    for (int i = 1; i <= n; i ++) fin >> V[i];
    for (int a, b, i = 1; i < n; i ++)
    {
        fin >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    Make_Paths();
    for (int t, a, b, i = 1; i <= m; i ++)
    {
        fin >> t >> a >> b;
        if (!t)
        {
            Update(1, 1, L_Dim[L[a]], Level[a] - L_Level[L[a]], b, L_Pos[L[a]]);
        }
        else
        {
            int sol = 0;
            while (L[a] != L[b])
            {
                if (L_Level[L[a]] < L_Level[L[b]])
                {
                    a ^= b ^= a ^= b;
                }
                sol = Maxim(sol, Query(1, 1, L_Dim[L[a]], 1, Level[a] - L_Level[L[a]], L_Pos[L[a]]));
                a = L_Tata[L[a]];
            }

            if (Level[a] > Level[b])
            {
                a ^= b ^= a ^= b;
            }
            sol = Maxim(sol, Query(1, 1, L_Dim[L[a]], Level[a] - L_Level[L[a]], Level[b] - L_Level[L[a]], L_Pos[L[a]]));
            fout << sol << '\n';
        }
    }
    fout.close();
    return 0;
}