Cod sursa(job #2082110)

Utilizator horiacoolNedelcu Horia Alexandru horiacool Data 5 decembrie 2017 18:42:44
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.64 kb
#include <iostream>
#include <stdio.h>
#include <vector>
#include <iterator>
using namespace std;
#define NMAX 100005
#define li long int
#define MIN(x,y) (niv[x] < niv[y]) ? x : y
#define compute(x,y) (v[x] > v[y]) ? x : y

int N, M, L, i, j, k, weight[NMAX], niv[NMAX], posINlant[NMAX], nrlant[NMAX], tatal[NMAX]; /// radacina lantului
li v[NMAX];
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;
    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;
            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 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];
        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_HPD(int x,int y)
{
    int sol = 0;
    while( true )
    {
        if( nrlant[x] == nrlant[y] )
        {
            sol = compute(sol , ST_query(posINlant[x], posINlant[y], nrlant[x], lant[nrlant[x]].size()) );
            break;
        }
        if( niv[ tatal[nrlant[x]] ] < niv[ tatal[nrlant[y]] ] )
           swap(x,y);
        sol = compute(sol , ST_query(posINlant[x], 1, nrlant[x], lant[nrlant[x]].size()) );
        x = tatal[nrlant[x]];
    }
    return sol;
}

int main()
{
    li 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("%ld",&v[i+1]);
    for(i = 1 ; i < N ; ++i)
    {
        scanf("%ld %ld", &x, &y);
        muchie[x].push_back(y);
        muchie[y].push_back(x);
    }
    rad = 1; L = 0;
    DFS1(rad,1); tatal[nrlant[rad]] = 0; ST_build();
    for(i = 0 ; i < M ; ++i)
    {
        scanf("%ld %ld %ld", &q, &x, &y);
        if( q == 0 )
            ST_modify(x,y);
        else
            printf("%ld\n", v[lant_sol_HPD(x,y)] );
    }
    return 0;
}