Cod sursa(job #1190425)

Utilizator andreiiiiPopa Andrei andreiiii Data 25 mai 2014 12:54:27
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.51 kb
#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

const int Nmax = 100005;

class SegmentTree {
public:
    SegmentTree() {}
    SegmentTree(vector<int> values)
    {
        for (N = 1; N < int(values.size()); N <<= 1);
        Aint = vector<int> (2 * N + 3, 0);

        for (int i = 0; i < int(values.size()); i++)
            Aint[N + i] = values[i];

        for (int i = N - 1; i; i--)
            Aint[i] = max(Aint[2 * i], Aint[2 * i + 1]);
    }

    void update(int poz, const int val)
    {
        Aint[poz += N] = val;
        for (poz >>= 1; poz; poz >>= 1)
            Aint[poz] = max(Aint[2 * poz], Aint[2 * poz + 1]);
    }

    int query(int left, int right)
    {
        left += N;
        right = N + min(right, N - 1);

        int ret = 0;
        while (left <= right)
        {
            ret = max(ret, max(Aint[left], Aint[right]));
            left = (left + 1) >> 1;
            right = (right - 1) >> 1;
        }

        return ret;
    }
private:
    int N;
    vector<int> Aint;
};

int A[Nmax], Path[Nmax], Nr[Nmax], Pos[Nmax], Lvl[Nmax], Father[Nmax];
vector<int> G[Nmax], Paths[Nmax], values;

int N, Nrpaths;

SegmentTree STrees[Nmax];

void Dfs1(const int node, const int father)
{
    if (father) G[node].erase(find(G[node].begin(), G[node].end(), father));

    Nr[node] = 1;

    int noden = 0;
    for (auto p: G[node])
    {
        Dfs1(p, node);

        Nr[node] += Nr[p];
        if (Nr[p] > Nr[noden])
            noden = p;
    }

    if (!noden) Path[node] = ++Nrpaths;
    else Path[node] = Path[noden];

    Paths[Path[node]].push_back(node);
}

void Dfs2(const int node)
{
    for (auto p: G[node])
    {
        if (Path[node] != Path[p])
        {
            Lvl[Path[p]] = Lvl[Path[node]] + 1;
            Father[Path[p]] = node;
        }

        Dfs2(p);
    }
}

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

    int Q;
    scanf("%d%d", &N, &Q);

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

    Dfs1(1, 0);

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

        for (int j = 0; j < int(Paths[i].size()); j++)
        {
            Pos[Paths[i][j]] = j;
            values.push_back(A[Paths[i][j]]);
        }

        STrees[i] = SegmentTree(values);

        Paths[i].clear();
        values.clear();
    }

    Dfs2(1);

    while (Q--)
    {
        int op, x, y;
        scanf("%d%d%d", &op, &x, &y);

        if (op == 0)
        {
            STrees[Path[x]].update(Pos[x], y);
        }
        else
        {
            int i = Path[x], j = Path[y], Sol = 0;

            while (i != j)
            {
                if (Lvl[i] > Lvl[j])
                {
                    Sol = max(Sol, STrees[i].query(0, Pos[x]));

                    x = Father[i];
                    i = Path[x];
                }
                else
                {
                    Sol = max(Sol, STrees[j].query(0, Pos[y]));

                    y = Father[j];
                    j = Path[y];
                }

           }

            Sol = max(Sol, STrees[i].query(min(Pos[x], Pos[y]), max(Pos[x], Pos[y])));

            printf("%d\n", Sol);
        }
    }
}