Cod sursa(job #2707424)

Utilizator Iulia14iulia slanina Iulia14 Data 16 februarie 2021 23:24:40
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.39 kb
#include <fstream>
#include <vector>
using namespace std;
ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");
#define pb push_back
#define ll int
const int NMAX = 100005;
const int N2 = 20;
vector <int> g[NMAX];
ll seg[4 * NMAX];
ll sz[NMAX];
ll heavy_child[NMAX];
ll label[NMAX];
ll depth[NMAX];
ll lift[N2][NMAX];
ll chain[NMAX];
ll a[NMAX];
ll dad[NMAX];
ll n;
ll combine(ll a, ll b)
{
    return max(a, b);
}
void update(int nod, int l, int r, int poz, int val)
{
    if (l == r)
    {
        seg[nod] = val;
        return;
    }
    int mid = (l + r) / 2, ls = 2 * nod, rs = ls + 1;
    if (poz <= mid)
        update(ls, l, mid, poz, val);
    else
        update(rs, mid + 1, r, poz, val);
    seg[nod] = combine(seg[ls], seg[rs]);
}
ll query(int nod, int l, int r, int ql, int qr)
{
    if (ql <= l && r <= qr)
        return seg[nod];
    if (l > r || r < ql || qr < l)
        return 0;
    int mid = (l + r) / 2, ls = 2 * nod, rs = ls + 1;
    ll a = query(ls, l, mid, ql, qr);
    ll b = query(rs, mid + 1, r, ql, qr);
    return combine(a, b);
}
void subarb(int nod)
{
    sz[nod] = 1;
    int maxi = -1;
    for (int i = 0; i < g[nod].size(); i++)
    {
        int x = g[nod][i];
        if (dad[x])
            continue;
        dad[x] = nod;
        lift[0][x] = nod;
        depth[x] = depth[nod] + 1;
        subarb(x);
        sz[nod] += sz[x];
        if (maxi == -1)
            maxi = x;
        else
        if (sz[x] > sz[maxi])
            maxi = x;
    }
    heavy_child[nod] = maxi;
}
void lifting()
{
    for (int i = 1; i < N2; i++)
        for (int j = 1; j <= n; j++)
            lift[i][j] = lift[i - 1][lift[i - 1][j]];
}
int LCA(int x, int y)
{
    int lg = N2 - 1;
    while (depth[x] < depth[y])
    {
        if (depth[x] <= depth[lift[lg][y]])
            y = lift[lg][y];
        lg--;
    }
    lg = N2 - 1;
    while (depth[x] > depth[y])
    {
        if (depth[y] <= depth[lift[lg][x]])
            x = lift[lg][x];
        lg--;
    }
    lg = N2 - 1;
    while (x != y && lg > -1)
    {
        if(lift[lg][x] != lift[lg][y])
        {
            x = lift[lg][x];
            y = lift[lg][y];
        }
        lg--;
    }
    if (x != y)
        return lift[0][x];
    return x;
}
void compute_chains(int nod)
{
    if (heavy_child[nod] != -1)
        chain[heavy_child[nod]] = chain[nod];
    for (int i = 0; i < g[nod].size(); i++)
    {
        int x = g[nod][i];
        if (x != dad[nod])
            compute_chains(x);
    }
}
int timp = 0;
void compute_labels(int nod)
{
    label[nod] = ++timp;
    update(1, 1, n, timp, a[nod]);
    if (heavy_child[nod] != -1)
        compute_labels(heavy_child[nod]);
    for (int i = 0; i < g[nod].size(); i++)
    {
        int x = g[nod][i];
        if (x != dad[nod] && x != heavy_child[nod])
            compute_labels(x);
    }
}
ll p2[N2];
int up(int x, int dist)
{
    for (int i = N2; i > -1; i--)
    {
        if (p2[i] <= dist)
        {
            dist -= p2[i];
            x = lift[i][x];
        }
    }
    return x;
}
ll query_chain(int x, int y)
{
    ll val = 0;
    while (depth[y] <= depth[x])
    {
        int boss = chain[x];
        if (depth[boss] < depth[y])
        {
            int dist = depth[x] - depth[y];
            boss = up(x, dist);
        }
        val = combine(val, query(1, 1, n, label[boss], label[x]));
        x = dad[boss];
    }
    return val;
}
int main()
{
    int i, q;
    cin >> n >> q;
    for (i = 1; i <= n; i++)
    {
        cin >> a[i];
        chain[i] = i;
    }
    for (i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dad[1] = -1;
    depth[1] = 1;
    subarb(1);
    lifting();
    compute_chains(1);
    compute_labels(1);
    p2[0] = 1;
    for (i = 1; i < N2; i++)
        p2[i] = 2 * p2[i - 1];
    while (q--)
    {
        int tip, x, y;
        cin >> tip;
        tip++;
        if (tip == 1)
        {
            cin >> x >> y;
            update(1, 1, n, label[x], y);
            continue;
        }
        cin >> x>> y;
        int lca = LCA(x, y);
        cout << combine(query(1, 1, n, label[lca], label[lca]), combine(query_chain(x, lca), query_chain(y, lca)))  << '\n';
        //cout << query_chain(x, 1) <<'\n';
    }
    return 0;
}