Cod sursa(job #1674367)

Utilizator AlexNiuclaeNiculae Alexandru Vlad AlexNiuclae Data 4 aprilie 2016 16:57:13
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.95 kb
///sursa folosind calea grea de descompunere...........

#include <bits/stdc++.h>

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

using namespace std;

const int Nmax = 1e5 + 10;
const int maxlog = 17;

int n , m , i , nrc;
int v[Nmax];
int lvl[Nmax] , w[Nmax] , fa[maxlog+1][Nmax];
int lbl[Nmax] , pos[Nmax] , nod[Nmax] , len[Nmax] , up[Nmax] , add[Nmax];
int arb[Nmax<<2];

vector < int > g[Nmax];

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

    fa[0][node] = dad;
    for (int i = 1; i <= maxlog; ++i)
        fa[i][node] = fa[i-1][fa[i-1][node]];

    for (auto &it : g[node])
    {
        if (it == dad) continue;
        dfs(it , node);
        w[node] += w[it];
    }
}

void chains(int node)
{
    lbl[node] = nrc;
    pos[node] = ++len[nrc];

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

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

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

        up[++nrc] = node;
        chains(it);
    }
}

int kanc(int x , int t)
{
    for (int i = 0; i <= maxlog; ++i)
        if (t & (1 << i))
            x = fa[i][x];

    return x;
}

int lca(int x , int y)
{
    if (lvl[x] < lvl[y]) swap(x , y);
    x = kanc(x , lvl[x] - lvl[y]);

    if (x == y) return x;

    for (int i = maxlog; i >= 0; --i)
        if (fa[i][x] != fa[i][y])
            x = fa[i][x] , y = fa[i][y];

    return fa[0][x];
}

void build(int node , int left , int right , int k)
{
    if (left == right)
    {
        arb[add[k]+node] = v[nod[add[k]+left]];
        return;
    }

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

    arb[add[k]+node] = max(arb[add[k]+leftSon] , arb[add[k]+rightSon]);
}

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

    int mid = (left + right) >> 1;

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

    arb[add[k]+node] = max(arb[add[k]+leftSon] , arb[add[k]+rightSon]);
}

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

    int mid = (left + right) >> 1; int ret = 0;

    if (lq <= mid) ret = max(ret , query(leftSon , left , mid , lq , rq , k));
    if (mid < rq) ret = max(ret , query(rightSon , mid + 1 , right , lq , rq , k));

    return ret;
}

int go(int x , int y)
{
    if (lvl[x] < lvl[y]) return 0;

    int L = (lbl[y] == lbl[x]) ? pos[y] : 1;
    int R = pos[x];

    int ret = query(1 , 1 , len[lbl[x]] , L , R , lbl[x]);
    return max(ret , go(up[lbl[x]] , 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 , 0);
    nrc = 1; chains(1);

    for (i = 2; i <= nrc + 1; ++i)
        add[i] = add[i-1] + (len[i-1] << 2);
    for (i = 1; i <= n; ++i)
        nod[add[lbl[i]]+pos[i]] = i;

    for (i = 1; i <= nrc; ++i)
        build(1 , 1 , len[i] , i);

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

        if (op == 0)
            update(1 , 1 , len[lbl[x]] , pos[x] , y , lbl[x]);
        else
        {
            int z = lca(x , y);
            int ans = max(go(x , z) , go(y , z));
            printf("%d\n", ans);
        }
    }

    return 0;
}