Cod sursa(job #1674493)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 4 aprilie 2016 18:04:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include <bits/stdc++.h>

#define leftSon (node << 1)
#define rightSon ((node << 1) | 1)

using namespace std;

const int Nmax = 1e5 + 10;

int n , m , i , nrc;
int v[Nmax];
int w[Nmax] , lvl[Nmax] , fa[Nmax];
int whr[Nmax] , pos[Nmax] , len[Nmax];
int *arb[Nmax];

vector < int > lbl[Nmax];
vector < int > g[Nmax];

void dfs(int node)
{
    w[node] = 1; lvl[node] = lvl[fa[node]] + 1;

    for (auto &it : g[node])
    {
        if (it == fa[node]) continue;

        fa[it] = node;
        dfs(it);

        w[node] += w[it];
    }
}

void chains(int node)
{
    whr[node] = nrc;
    lbl[nrc].push_back(node);
    pos[node] = (int)lbl[nrc].size();

    int maxx = 0, to = -1;
    for (auto &it : g[node])
    {
        if (it == fa[node]) continue;
        if (w[it] > maxx)
            maxx = w[it], to = it;
    }

    if (to != -1) chains(to);

    for (auto &it : g[node])
    {
        if (it == fa[node]) continue;
        if (it == to) continue;

        nrc++;
        chains(it);
    }
}

void build(int node , int left , int right , int ind)
{
    if (left == right)
    {
        arb[ind][node] = v[lbl[ind][left-1]];
        return;
    }

    int mid = (left + right) >> 1;
    build(leftSon , left , mid , ind);
    build(rightSon , mid + 1 , right , ind);

    arb[ind][node] = max(arb[ind][leftSon] , arb[ind][rightSon]);
}

void update(int node , int left , int right , int pu , int vu , int ind)
{
    if (left == right)
    {
        arb[ind][node] = vu;
        return;
    }

    int mid = (left + right) >> 1;
    if (pu <= mid) update(leftSon , left , mid , pu , vu , ind);
    else update(rightSon , mid + 1 , right , pu , vu , ind);

    arb[ind][node] = max(arb[ind][leftSon] , arb[ind][rightSon]);
}

int query(int node , int left , int right , int lq , int rq , int ind)
{
    if (lq <= left && right <= rq)
        return arb[ind][node];

    int mid = (left + right) >> 1; int ret = 0;
    if (lq <= mid) ret = max(ret , query(leftSon , left , mid , lq , rq , ind));
    if (mid < rq) ret = max(ret , query(rightSon , mid + 1 , right , lq , rq , ind));

    return ret;
}

int go(int x , int y)
{
    if (whr[x] == whr[y])
    {
        if (pos[x] > pos[y]) swap(x , y);
        return query(1 , 1 , len[whr[x]] , pos[x] , pos[y] , whr[x]);
    }

    int dadx = lbl[whr[x]][0]; int dady = lbl[whr[y]][0];
    if (lvl[dadx] < lvl[dady])
        swap(x , y);

    int ret = query(1 , 1 , len[whr[x]] , 1 , pos[x] , whr[x]);
    return max(ret , go(fa[lbl[whr[x]][0]] , y));
}

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

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

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

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

    dfs(1);
    nrc = 1; chains(1);

    for (i = 1; i <= nrc; ++i)
    {
        len[i] = (int)lbl[i].size();
        arb[i] = new int [len[i]<<2];
        build(1 , 1 , len[i] , i);
    }

    for (i = 1; i <= m; ++i)
    {
        int op , x , y;
        scanf("%d %d %d", &op, &x, &y);

        if (op == 0) update(1 , 1 , len[whr[x]] , pos[x] , y , whr[x]);
        else printf("%d\n", go(x , y));
    }

    return 0;
}