Cod sursa(job #1492089)

Utilizator ZenusTudor Costin Razvan Zenus Data 27 septembrie 2015 02:18:57
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.49 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 fc[nmax] , f[nmax] , w[nmax] , lbl[nmax] , whr[nmax] , v[nmax] , d[nmax];
vector < int > g[nmax] , chain[nmax] , aint[nmax];
int n , q , x , y , nrc , i , j , type , iw , p , m , z , res;
int pa[LOG + 1][nmax];

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

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

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

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

int query(int k , int x , int l , int r , int lq , int rq)
{
    if (r < lq || rq < l) return 0;

    if (lq <= l && r <= rq)
    return aint[k][x];

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

    return max(query(k , 2 * x , l , c , lq , rq) , query(k , 2 * x + 1 , c + 1 , r , lq , rq));
}

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;
    f[x] = fa;
    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 , aux = nrc;

    if (chain[nrc].empty()) chain[nrc].push_back(0);

    lbl[x] = nrc , whr[x] = chain[nrc].size();
    chain[nrc].push_back(x);

    for (auto j = g[x].begin() ; j != g[x].end() ; ++j)
    {
        int y = *j;
        if (y == f[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 == f[x] || y == to) continue;

        fc[nrc] = aux;

        doChains(y);
    }
}

void doInit()
{
    for (i = 1 ; i < nrc ; ++i)
    {
        int m = chain[i].size() - 1;

        aint[i].resize(3 * m);

        for (j = 1 ; j <= m ; ++j)
        change(i , 1 , 1 , m , j , v[chain[i][j]]);
    }
}

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

    if (lbl[z] == iw)
    from = whr[z];
    else from = 1;

    int m = chain[iw].size() - 1;
    int ans = query(iw , 1 , 1 , m , from , to);

    if (lbl[z] == lbl[x]) return ans;
    int up = chain[iw][1];
    return max(go(f[up] , z) , ans);
}

int main()
{

fin >> n >> q;

for (i = 1 ; i <= n ; ++i)
fin >> v[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);

doInit();

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

    if (type == 0)
    {
        iw = lbl[x];
        p = whr[x];
        m = chain[iw].size() - 1;
        change(iw , 1 , 1 , m , p , y);
    }
    else
    {
        z = lca(x , y);
        res = go(x , z);
        res = max(res , go(y , z));
        fout << res << '\n';
    }
}

return 0;
}