Cod sursa(job #1492097)

Utilizator ZenusTudor Costin Razvan Zenus Data 27 septembrie 2015 02:48:26
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.32 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

const int nmax = 100000 + 10;
const int LOG = 17;

int pa[LOG + 1][nmax];
int tmp[nmax] , w[nmax] , d[nmax] , len[nmax] , lbl[nmax] , whr[nmax] , up[nmax] , aint[3 * nmax] , add[nmax];
vector < int > g[nmax];
int n , q , x , y , type , nrc , i , res , j , z;

void DP()
{
    for (int i = 1 ; i <= LOG ; ++i)
    for (int j = 1 ; j <= n ; ++j)
    pa[i][j] = pa[i - 1][pa[i - 1][j]];
}

int kanc(int n , int k)
{
    for (int i = LOG ; i >= 0 ; --i)
    if ( (1 << i) <= k)
    {
        k -= (1 << i);
        n = pa[i][n];
    }

    return n;
}

int lca(int x , int y)
{
    // x is deeper than y
    if (d[x] < d[y]) swap(x , y);

    int q = d[x] - d[y];
    x = kanc(x , q);
    if (x == y) return x;

    //now x is at same level with y

    for (int i = LOG ; i >= 0 ; --i)
    if (pa[i][x] != pa[i][y])
    {
        x = pa[i][x];
        y = pa[i][y];
    }

    return pa[0][x];
}

void df(int x , int fa)
{
    w[x] = 1;
    d[x] = d[fa] + 1;
    pa[0][x] = fa;

    for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
    {
        int y = *j;
        if (y == fa) continue;
        df(y , x);
        w[x] += w[y];
    }
}

void doChains(int x)
{
    int to = 0;

    len[nrc] += 1;
    lbl[x] = nrc , whr[x] = len[nrc];

    for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
    {
        int y = *j;
        if (y == pa[0][x]) continue;

        if (w[*j] > w[to]) to = *j;
    }

    if (to)
    doChains(to);
    else ++nrc;

    for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
    {
        int y = *j;
        if (y == pa[0][x] || y == to) continue;

        up[nrc] = x;
        doChains(y);
    }
}

void change(int k , int x , int l , int r , int p , int y , int add)
{
    if (l == r)
    {
        aint[add + x] = y;
        return ;
    }

    int m = (l + r) >> 1;

    if (p <= m)
    change(k , 2 * x , l , m , p , y , add);
    else change(k , 2 * x + 1 , m + 1 , r , p , y , add);

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

void query(int k , int x , int l , int r , int lq , int rq , int add)
{
    if (lq <= l && r <= rq)
    {

        res = max(res , aint[add + x]);
        return ;
    }

    int m = (l + r) >> 1;

    if (m >= lq)
    query(k , 2 * x , l , m , lq , rq , add);

    if (m < rq)
    query(k , 2 * x + 1 , m + 1 , r , lq , rq , add);
}

void go(int x , int z)
{
    int j = lbl[x];
    int from = whr[x];
    int to;

    if (lbl[z] == j)
    to = whr[z];
    else to = 1;

    query(j , 1 , 1 , len[j] , to , from , add[j]);

    if (lbl[x] == lbl[z]) return ;
    go(up[j] , z);
}

int main()
{

fin >> n >> q;

for (i = 1 ; i <= n ; ++i)
fin >> tmp[i];

for (i = 1 ; i < n ; ++i)
{
    fin >> x >> y;
    g[x].push_back(y);
    g[y].push_back(x);
}

df(1 , 0);
DP();

nrc = 1;
doChains(1);
nrc -= 1;

add[1] = 0;

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

for (i = 1 ; i <= n ; ++i)
{
    j = lbl[i];
    change(j , 1 , 1 , len[j] , whr[i] , tmp[i] , add[j]);
}

for (i = 1 ; i <= q ; ++i)
{
    fin >> type >> x >> y;

    if (type == 0)
    {
        j = lbl[x];
        change(j , 1 , 1 , len[j] , whr[x] , y , add[j]);
    }
    else
    {
        z = lca(x , y);

        res = 0;
        go(x , z);
        go(y , z);

        fout << res << '\n';
    }
}

return 0;
}