Cod sursa(job #2082069)

Utilizator horiacoolNedelcu Horia Alexandru horiacool Data 5 decembrie 2017 17:59:50
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.39 kb
#include <iostream>
#include <stdio.h>
#include <vector>
#include <iterator>
using namespace std;
#define NMAX 100005
#define logNMAX 20
#define MIN(x,y) (niv[x] < niv[y]) ? x : y
#define compute(x,y) (v[x] > v[y]) ? x : y

int N, M, K, L, i, j, k, v[NMAX], weight[NMAX], niv[NMAX], pos[NMAX], lg[2*NMAX], ET[logNMAX][2*NMAX], posINlant[NMAX], nrlant[NMAX];
int tatal[NMAX]; /// radacina lantului
int *stlant[NMAX];
vector<int>muchie[NMAX], lant[NMAX];

int DFS1(int xp,int h)
{
    int wxp, imw, mw, w, ok, l; /// wxp weight xp, imw index max weight, mx max weight, w of sons, ok marcheaza frunza, l lant xp
    wxp = imw = mw = w = ok = 0;
    ET[0][++K] = xp;
    pos[xp] = K;
    niv[xp] = h;

    for(vector<int>::iterator it = muchie[xp].begin() ; it != muchie[xp].end() ; ++it)
        if( niv[*it] == 0 )
        {
            ok = 1;
            w = DFS1(*it,h+1);
            wxp += w + 1;
            ET[0][++K] = xp; /// introduc xp in parcurgerea euleriana dupa fiecare fiu
            tatal[nrlant[*it]] = xp; /// radacina lanturilor fiilor este xp

            if( mw <= w ) /// sa stiu pe care lant al fiilor il aleg
            {
                imw = *it;
                 mw = w;
            }
        }

    if( ok == 0 ) /// creez un lant nou in frunze
        l = ++L;
    else
        l = nrlant[imw];

    nrlant[xp] = l;
    lant[l].push_back(xp);
    posINlant[xp] = lant[l].size();

    return wxp;
}

void RMQ_build()
{
    lg[1] = 0;
    for(i = 2 ; i <= K ; ++i)
        lg[i] = lg[i/2] + 1;

    for(i = 1 ; i <= lg[K] ; ++i)
        for(j = 1 ; j <= K ; ++j)
            ET[i][j] = MIN( ET[i-1][j] , ET[i-1][j+(1<<(i-1))] );
}

int lca(int x, int y)
{
    int p1,p2,l;
    p1 = min(pos[x], pos[y]);
    p2 = max(pos[x], pos[y]);
    l = lg[p2-p1+1];

    return MIN( ET[l][p1] , ET[l][p2-(1<<l)+1] );
}

void ST_build()
{
    for(i = 1 ; i <= N ; ++i)
        posINlant[i] = lant[nrlant[i]].size() -  posINlant[i] + 1; /// atribui pozitia corecta in lant de sus in jos

    for(i = 1 ; i <= L ; ++i)
    {
        int n = lant[i].size();
        stlant[i] = new int[2*n+5]; /// +5 sa nu iasa din memorie
        for(k = 0 ; k < 2*n ; ++k)
            stlant[i][k] = 0;

        for(vector<int>::iterator it = lant[i].begin() ; it != lant[i].end() ; ++it)
            stlant[i][n+( posINlant[*it]-1 )] = *it;

        for(k = n-1 ; k > 0 ; --k)
            stlant[i][k] = compute(stlant[i][k*2] , stlant[i][k*2+1]);
    }
}

void ST_modify(int xp,int val)
{
    int n,l,p;
    v[xp] = val;
    l = nrlant[xp];
    n = lant[l].size();
    p = posINlant[xp];

    for(p += n-1 ; p > 0 ; p >>= 1)
        stlant[l][p>>1] = compute(stlant[l][p] , stlant[l][p^1]);
}

int ST_query(int p1, int p2, int l , int n)
{
    int left, right, sol = 0; v[sol] = 0;
    left = min(p1 , p2);
    right= max(p1 , p2);

    for(left += n-1, right += n-1 ; left <= right ; left >>= 1 , right >>= 1)
    {
        if( left % 2 == 1 ) { sol = compute(sol, stlant[l][left]);   left++; }
        if(right % 2 == 0 ) { sol = compute(sol, stlant[l][right]); right--; }
    }
    return sol;
}

int lant_sol(int x,int lcaxy)
{
    int sol = 0;
    while( true )
    {
        if( nrlant[x] == nrlant[lcaxy] )
        {
            sol = compute(sol , ST_query(posINlant[x], posINlant[lcaxy], nrlant[x], lant[nrlant[x]].size()) );
            break;
        }
        else
        {
            sol = compute(sol , ST_query(posINlant[x], 1, nrlant[x], lant[nrlant[x]].size()) );
            x = tatal[nrlant[x]];
        }
    }
    return sol;
}

int ValMaxHPD(int x, int y)
{
    int lcaxy = lca(x,y);
    return v[ compute(lant_sol(x,lcaxy) , lant_sol(y,lcaxy)) ];
}

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

    scanf("%d %d", &N, &M);

    for(i = 0 ; i < N ; ++i)
        scanf("%d",&v[i+1]);

    for(i = 1 ; i < N ; ++i)
    {
        scanf("%d %d", &x, &y);
        muchie[x].push_back(y);
        muchie[y].push_back(x);
    }

    rad = 1;
    K = 0; L = 0;
    DFS1(rad,1); tatal[nrlant[rad]] = 0; RMQ_build(); ST_build();

    for(i = 0 ; i < M ; ++i)
    {
        scanf("%d %d %d", &q, &x, &y);
        if( q == 0 )
            ST_modify(x,y);
        else
            printf("%d\n", ValMaxHPD(x,y));
    }
    return 0;
}