Cod sursa(job #1139730)

Utilizator poptibiPop Tiberiu poptibi Data 11 martie 2014 13:43:14
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.2 kb
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;

#define LeftSon (2 * Node)
#define RightSon (2 * Node + 1)

const int NMAX = 100010;

int N, M, X, Y, Type, NrChains, Ans, Level[NMAX], Weight[NMAX], Val[NMAX], Aint[4 * NMAX];
int Chain[NMAX], ChainDim[NMAX], ChainStart[NMAX], ChainFather[NMAX], ChainLevel[NMAX], ChainPos[NMAX];
bool Used[NMAX];
vector<int> G[NMAX], ChainNodes[NMAX];

void DFS(int Node, int Father)
{
    Used[Node] = 1;
    Level[Node] = Level[Father] + 1;
    Weight[Node] = 1;

    bool Leaf = 1;
    int Heaviest = 0;

    for(vector<int> :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
        if(!Used[*it])
        {
            Leaf = 0;
            DFS(*it, Node);
            Weight[Node] += Weight[*it];
            if(Weight[*it] > Weight[Heaviest])
                Heaviest = *it;
        }

    if(Leaf)
    {
        Chain[Node] = ++ NrChains;
        ChainDim[NrChains] ++;
        ChainNodes[NrChains].push_back(Node);
    }else
    {
        Chain[Node] = Chain[Heaviest];
        ChainDim[Chain[Node]] ++;
        ChainNodes[Chain[Node]].push_back(Node);

        for(vector<int> :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
            if(*it != Father && *it != Heaviest)
            {
                ChainLevel[Chain[*it]] = Level[Node];
                ChainFather[Chain[*it]] = Node;
            }
    }
}

void Build(int Node, int Left, int Right, int Delay, int IndexChain)
{
    if(Left >= Right)
    {
        Aint[Node + Delay] = Val[ ChainNodes[IndexChain][Left - 1] ];
        return ;
    }
    int Mid = (Left + Right) / 2;
    Build(LeftSon, Left, Mid, Delay, IndexChain);
    Build(RightSon, Mid + 1, Right, Delay, IndexChain);
    Aint[Node + Delay] = max(Aint[LeftSon + Delay], Aint[RightSon + Delay]);
}

void Path_Decomposition()
{
    DFS(1, 0);

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

        for(int j = 0; j < ChainNodes[i].size(); ++ j)
            ChainPos[ ChainNodes[i][j] ] = j + 1;

        ChainStart[i] = ChainStart[i - 1] + 4 * ChainDim[i - 1];
        Build(1, 1, ChainDim[i], ChainStart[i], i);
    }
}

void Update(int Node, int Left, int Right, int Delay, int Pos, int Val)
{
    if(Left == Right)
    {
        Aint[Node + Delay] = Val;
        return ;
    }
    int Mid = (Left + Right) / 2;
    if(Pos <= Mid) Update(LeftSon, Left, Mid, Delay, Pos, Val);
    else Update(RightSon, Mid + 1, Right, Delay, Pos, Val);

    Aint[Node + Delay] = max(Aint[LeftSon + Delay], Aint[RightSon + Delay]);
}

void Query(int Node, int Left, int Right, int Delay, int LeftBound, int RightBound)
{
    if(LeftBound <= Left && Right <= RightBound)
    {
        Ans = max(Ans, Aint[Node + Delay]);
        return ;
    }
    int Mid = (Left + Right) / 2;
    if(LeftBound <= Mid) Query(LeftSon, Left, Mid, Delay, LeftBound, RightBound);
    if(Mid < RightBound) Query(RightSon, Mid + 1, Right, Delay, LeftBound, RightBound);
}

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

    scanf("%i %i", &N, &M);
    for(int i = 1; i <= N; ++ i) scanf("%i", &Val[i]);

    for(int i = 1; i < N; ++ i)
    {
        scanf("%i %i", &X, &Y);
        G[X].push_back(Y);
        G[Y].push_back(X);
    }

    Path_Decomposition();

    for(; M; M --)
    {
        scanf("%i %i %i", &Type, &X, &Y);
        if(Type == 0) Update(1, 1, ChainDim[Chain[X]], ChainStart[Chain[X]], ChainPos[X], Y);
        else
        {
            Ans = 0;
            while(1)
            {
                if(Chain[X] == Chain[Y])
                {
                    if(Level[X] >= Level[Y]) swap(X, Y);
                    Query(1, 1, ChainDim[Chain[X]], ChainStart[Chain[X]], ChainPos[X], ChainPos[Y]);
                    break;
                }

                if(ChainLevel[Chain[X]] < ChainLevel[Chain[Y]]) swap(X, Y);
                Query(1, 1, ChainDim[Chain[X]], ChainStart[Chain[X]], 1, ChainPos[X]);
                X = ChainFather[Chain[X]];
            }
            printf("%i\n", Ans);
        }
    }
}