Cod sursa(job #1784602)

Utilizator team_nameUPB Banu Popa Visan team_name Data 20 octombrie 2016 11:42:10
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.92 kb
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;

#define leftson (2 * node)
#define rightson (2 * node + 1)

const int nmax = 100010;

int n, m, v[nmax], a, b, t, x, y, aint[4 * nmax], level[nmax];
vector<int> g[nmax], chain[nmax];
bool used[nmax];
int sub[nmax], nrch, chainstart[nmax], chainfather[nmax], chainpos[nmax], chainindex[nmax], chainsize[nmax];

void dfs(int node, int father)
{
    level[node] = level[father] + 1;
    sub[node] = 1;
    bool is_leaf = 1;
    int heaviest = -1;

    for (int vec : g[node])
    {
        if (vec == father) continue;
        is_leaf = 0;
        dfs(vec, node);

        if (heaviest == -1 || sub[vec] > sub[heaviest])
            heaviest = vec;
        sub[node] += sub[vec];
    }

    if (is_leaf)
    {
        ++ nrch;
        chain[nrch].push_back(node);
        chainindex[node] = nrch;
        chainsize[nrch] ++;
    }else
    {
        for (int vec : g[node])
        {
            if (vec == father) continue;
            if (vec == heaviest)
            {
                chainindex[node] = chainindex[vec];
                chain[chainindex[node]].push_back(node);
                chainsize[chainindex[node]] ++;
            }else
                chainfather[chainindex[vec]] = node;
        }
    }
}

void update(int node, int left, int right, int shift, int pos, int val)
{
    if (left == right)
    {
        aint[node + shift] = val;
        return ;
    }
    int mid = (left + right)/ 2;
    if (pos <= mid)
        update(leftson, left, mid, shift, pos, val);
    else
        update(rightson, mid + 1, right, shift, pos, val);
    aint[node + shift] = max(aint[leftson + shift], aint[rightson + shift]);
}

int query(int node, int left, int right, int shift, int leftb, int rightb)
{
    if (leftb <= left && right <= rightb)
        return aint[node + shift];
    int mid = (left + right) / 2, now = 0;
    if (leftb <= mid)
        now = max(now, query(leftson, left, mid, shift, leftb, rightb));
    if (mid < rightb)
        now = max(now, query(rightson, mid + 1, right, shift, leftb, rightb));
    return now;
}

void build_decomp()
{
    for (int i = 1; i <= nrch; ++ i)
    {
        chainstart[i] = chainstart[i - 1] + 4 * chainsize[i - 1];
        reverse(chain[i].begin(), chain[i].end());
        for (int j = 0; j < chain[i].size(); ++ j)
        {
            chainpos[chain[i][j]] = j + 1;
            update(1, 1, chainsize[i], chainstart[i], j + 1, v[chain[i][j]]);
        }
    }
}

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

    //freopen("in", "r", stdin);

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

    dfs(1, 0);
    build_decomp();

    for (; m; -- m)
    {
        scanf("%i %i %i", &t, &x, &y);
        if (t == 0)
        {
            v[x] = y;
            update(1, 1, chainsize[chainindex[x]], chainstart[chainindex[x]], chainpos[x], y);
        }else
        {
            int ans = 0;
            while (1)
            {
                if (chainindex[x] == chainindex[y])
                {
                    if (chainpos[x] > chainpos[y]) swap(x, y);
                    ans = max(ans, query(1, 1, chainsize[chainindex[x]], chainstart[chainindex[x]], chainpos[x], chainpos[y]));
                    break;
                }
                if (level[chainfather[chainindex[x]]] < level[chainfather[chainindex[y]]])
                    swap(x, y);
                ans = max(ans, query(1, 1, chainsize[chainindex[x]], chainstart[chainindex[x]], 1, chainpos[x]));
                x = chainfather[chainindex[x]];
            }
            printf("%d\n", ans);
        }
    }
}