Cod sursa(job #1651057)

Utilizator DrumeaVDrumea Vasile DrumeaV Data 12 martie 2016 00:40:01
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.47 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int Mn = 1e5 + 6;

int n, m, cnt, it, sol;
int val[Mn], weight[Mn], parent[Mn], depth[Mn], wpath[Mn], wpos[Mn], pathsz[Mn], pathhead[Mn];
char buff[Mn];
vector< int > g[Mn], tree[Mn];

void read(int &num)
{
    num = 0;
    char sign = '+';
    while (!isdigit(buff[it]))
    {
        sign = buff[it];
        if (++it == Mn)
           fread(buff, 1, Mn, stdin), it = 0;
    }

    while (isdigit(buff[it]))
    {
        num = num * 10 + buff[it] - '0';
        if (++it == Mn)
           fread(buff, 1, Mn, stdin), it = 0;
    }

    if (sign == '-')
       num *= -1;
}

void dfs(int x)
{
    weight[x] = 1;
    for (auto node : g[x])
        if (!weight[node])
        {
            parent[node] = x;
            depth[node] = depth[x] + 1;
            dfs(node);
            weight[x] += weight[node];
        }
}

void hld(int x,int id)
{
    wpath[x] = id;
    wpos[x] = ++pathsz[id];

    int mx = 0;
    for (auto node : g[x])
        if (node != parent[x] && weight[node] > weight[mx])
           mx = node;

    if (!mx)
       return;

    hld(mx, id);
    for (auto node : g[x])
        if (node != parent[x] && node != mx)
        {
            pathhead[++cnt] = x;
            hld(node, cnt);
        }
}

void update(int node, int l, int r, int id, int value)
{
    if (!id)
       return;

    if (l == r)
    {
        tree[wpath[id]][node] = value;
        return;
    }

    int m = (l + r) / 2;
    if (wpos[id] <= m)
       update(2 * node, l, m, id, value);
  else
       update(2 * node + 1, m + 1, r, id, value);

    tree[wpath[id]][node] = max(tree[wpath[id]][2 * node], tree[wpath[id]][2 * node + 1]);
}

void query(int node, int l, int r, int fi, int la, int id)
{
    if (!id)
       return;

    if (fi <= l && r <= la)
    {
        sol = max(sol, tree[wpath[id]][node]);
        return;
    }

    int m = (l + r) / 2;
    if (fi <= m)
       query(2 * node, l, m, fi, la, id);

    if (m < la)
       query(2 * node + 1, m + 1, r, fi, la, id);
}

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

    read(n); read(m);
    for (int i = 1; i <= n; i++)
        read(val[i]);

    for (int i = 1; i < n; i++)
    {
        int a, b;
        read(a); read(b);
        g[a].push_back(b);
        g[b].push_back(a);
    }

    dfs(1);
    hld(1, ++cnt);
    for (int i = 1; i <= cnt; i++)
        tree[i].resize(4 * pathsz[i]);

    for (int i = 1; i <= n; i++)
        update(1, 1, pathsz[wpath[i]], i, val[i]);

    for (; m; m--)
    {
        int t, x, y;
        read(t); read(x); read(y);
        if (t == 0)
           update(1, 1, pathsz[wpath[x]], x, y);
      else
        {
            int ans = 0;
            while (x && y && wpath[x] != wpath[y])
            {
                if (depth[pathhead[wpath[x]]] < depth[pathhead[wpath[y]]])
                   swap(x,y);

                sol = 0;
                query(1, 1, pathsz[wpath[x]], 1, wpos[x], x);
                ans = max(ans, sol);
                x = pathhead[wpath[x]];
            }

            if (wpos[x] > wpos[y])
               swap(x,y);

            sol = 0;
            query(1, 1, pathsz[wpath[x]], wpos[x], wpos[y], x);
            ans = max(ans, sol);
            printf("%d\n", ans);
        }
    }

  return 0;
}