Cod sursa(job #1439724)

Utilizator UPB_Radu_Stefan_SilviuDont Blink UPB_Radu_Stefan_Silviu Data 23 mai 2015 00:11:32
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.31 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, V[NMAX], Type, X, Y, Aint[4 * NMAX], Level[NMAX];
int ChainLevel[NMAX], ChainIndex[NMAX], ChainDim[NMAX], ChainStart[NMAX], ChainPos[NMAX], ChainFather[NMAX], Weight[NMAX], NC;
vector<int> Chain[NMAX];
vector<int> G[NMAX];
bool Used[NMAX];

void DFS(int Node, int Father)
{
    Used[Node] = 1;
    Level[Node] = Level[Father] + 1;
    bool Leaf = 1;
    Weight[Node] = 1;
    int Max = 0, Heaviest = 0;

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

    if(Leaf == 1)
    {
        ++ NC;
        Chain[NC].push_back(Node);
        ChainIndex[Node] = NC;
        ChainDim[NC] ++;
    }else
    {
        ChainIndex[Node] = ChainIndex[Heaviest];
        ChainDim[ ChainIndex[Node] ] ++;
        Chain[ ChainIndex[Node] ].push_back(Node);

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

void Build(int Node, int Left, int Right, int Delay, int IndexChain)
{
    if(Left == Right)
    {
        Aint[Node + Delay] = V[ Chain[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 PathDecomposition()
{
    DFS(1, 0);

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

        ChainStart[i] = ChainStart[i - 1] + 4 * ChainDim[i - 1];
        for(int j = 0; j < Chain[i].size(); ++ j)
            ChainPos[ Chain[i][j] ] = j + 1;

        Build(1, 1, ChainDim[i], ChainStart[i], i);
    }
}

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

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

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", &V[i]);

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

    PathDecomposition();

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

                if(ChainLevel[ChainIndex[X]] <= ChainLevel[ChainIndex[Y]]) swap(X, Y);
                Ans = max(Ans, Query(1, 1, ChainDim[ ChainIndex[X] ], 1, ChainPos[X], ChainStart[ ChainIndex[X] ]));
                X = ChainFather[ ChainIndex[X] ];
            }

            printf("%i\n", Ans);
        }
    }
}