Cod sursa(job #1689487)

Utilizator ZenusTudor Costin Razvan Zenus Data 14 aprilie 2016 12:05:47
Problema Heavy Path Decomposition Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.35 kb
#include <bits/stdc++.h>

using namespace std;

const int nmax = 100009;
const int lgmax = 19;

int dad[lgmax][nmax];
int st[4 * nmax];
int add[nmax] , whr[nmax] , label[nmax] , lvl[nmax];
int w[nmax] , len[nmax] , roof[nmax] , x[nmax];
int answer , n , q , a , b , v , t , cnt , i , j;
vector < int > g[nmax];

void dfs(int act , int up)
{
    dad[0][act] = up;
    lvl[act] = lvl[up] + 1;
    w[act] = 1;

    for (int i = 0 ; i < g[act].size() ; ++i)
    if (g[act][i] == up)
    {
        g[act].erase(g[act].begin() + i);
        break;
    }

    for (int i = 0 ; i < g[act].size() ; ++i)
    {
        dfs(g[act][i] , act);
        w[act] += w[g[act][i]];
    }
}

void getChains(int act)
{
    label[act] = cnt;
    whr[act] = ++len[cnt];

    int p = 0;
    for (int i = 0 ; i < g[act].size() ; ++i)
    if (w[g[act][i]] > w[p]) p = g[act][i];

    if (p) getChains(p);
    else cnt++;

    for (int i = 0 ; i < g[act].size() ; ++i)
    if (g[act][i] - p)
    {
        roof[cnt] = act;
        getChains(g[act][i]);
    }
}

int kanc(int x , int p)
{
    for (int i = 0 ; (1 << i) <= p ; ++i)
    if ((1 << i) & p) x = dad[i][x];

    return x;
}

int lca(int a , int b)
{
    if (lvl[a] < lvl[b]) swap(a , b);

    a = kanc(a , lvl[a] - lvl[b]);
    if (a == b) return a;

    for (int i = 0 ; (1 << i) <= lvl[a] ; ++i)
    if (dad[i][a] != dad[i][b]) a = dad[i][a] , b = dad[i][b];

    return dad[0][a];
}

void update(int x , int l , int r , int p , int v , int add)
{
    if (l == r)
    {
        st[x + add] = v;
        return;
    }

    int c = (l + r) / 2;

    if (p <= c) update(2 * x , l , c , p , v , add);
    else update(2 * x + 1 , c + 1 , r , p , v , add);

    st[x + add] = max(st[2 * x + add] , st[2 * x + 1 + add]);
}

void query(int x , int l , int r , int lq , int rq , int add)
{
    if (lq <= l && r <= rq)
    {
        answer = max(answer , st[x + add]);
        return;
    }

    int c = (l + r) / 2;
    if (lq <= c) query(2 * x , l , c , lq , rq , add);
    if (c < rq) query(2 * x + 1 , c + 1 , r , lq , rq , add);
}

void walk(int x , int up)
{
    if (label[x] == label[up])
    {
        query(1 , 1 , len[label[x]] , whr[up] , whr[x] , add[label[x]]);
        return ;
    }

    query(1 , 1 , len[label[x]] , 1 , whr[x] , add[label[x]]);
    walk(roof[label[x]] , up);
}

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

scanf("%d" , &n);
scanf("%d" , &q);

for (i = 1 ; i <= n ; ++i)
scanf("%d" , &x[i]);

for (i = 2 ; i <= n ; ++i)
{
    scanf("%d" , &a);
    scanf("%d" , &b);

    g[a].push_back(b);
    g[b].push_back(a);
}

dfs(1 , 0);

for (i = 1 ; (1 << i) <= n ; ++i)
for (j = 1 ; j <= n ; ++j)
dad[i][j] = dad[i - 1][dad[i - 1][j]];

cnt = 1;
getChains(1);
cnt--;

for (i = 2 ; i <= cnt ; ++i)
add[i] = add[i - 1] + 4 * len[i - 1];

for (i = 1 ; i <= n ; ++i)
update(1 , 1 , len[label[i]] , whr[i] , x[i] , add[label[i]]);

for (i = 1 ; i <= q ; ++i)
{
    scanf("%d" , &t);
    scanf("%d" , &a);
    scanf("%d" , &b);

    if (t == 0)
    update(1 , 1 , len[label[a]] , whr[a] , b , add[label[a]]);
    else
    {
        v = lca(a , b);

        answer = 0;
        walk(a , v);
        walk(b , v);
        printf("%d\n" , answer);
    }
}

return 0;
}