Cod sursa(job #1651113)

Utilizator DrumeaVDrumea Vasile DrumeaV Data 12 martie 2016 11:31:55
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.07 kb
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int Mn = 1e5 + 6;

int n, m, cnt, sol;
int val[Mn], weight[Mn], parent[Mn], depth[Mn], path[Mn], pos[Mn], psize[Mn], proot[Mn];
vector< int > g[Mn], tree[Mn];

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)
{
    path[x] = id;
    pos[x] = ++psize[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)
        {
            proot[++cnt] = x;
            hld(node, cnt);
        }
}

void update(int node, int l, int r, int value, int pos, vector< int > &st)
{
    if (l == r)
    {
        st[node] = value;
        return;
    }

    int m = (l + r) / 2;
    if (pos <= m)
       update(2 * node, l, m, value, pos, st);
  else
       update(2 * node + 1, m + 1, r, value, pos, st);

    st[node] = max(st[2 * node], st[2 * node + 1]);
}

void query(int node, int l, int r, int fi, int la, vector< int > &st)
{
    if (fi <= l && r <= la)
    {
        sol = max(sol, st[node]);
        return;
    }

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

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

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

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

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

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

    for (int i = 1; i <= n; i++)
        update(1, 1, psize[path[i]], val[i], pos[i], tree[path[i]]);

    for (; m; m--)
    {
        int t, x, y;
        scanf("%d %d %d", &t, &x, &y);
        if (t == 0)
           update(1, 1, psize[path[x]], y, pos[x], tree[path[x]]);
      else
        {
            int ans = 0;
            int nr = 0;
            while (nr < 10 && path[x] != path[y])
            {
                nr++;
                if (depth[proot[path[x]]] < depth[proot[path[y]]])
                   swap(x,y);

                sol = 0;
                query(1, 1, psize[path[x]], 1, pos[x], tree[path[x]]);
                ans = max(ans, sol);
                x = proot[path[x]];
            }

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

            sol = 0;
            query(1, 1, psize[path[x]], pos[x], pos[y], tree[path[x]]);
            ans = max(ans, sol);
            printf("%d\n", ans);
        }
    }

  return 0;
}