Cod sursa(job #2707620)

Utilizator Iulia14iulia slanina Iulia14 Data 17 februarie 2021 14:43:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.29 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 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;
        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 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 main()
{
    int i, q;
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    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);
    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 ans = 0;
        while (chain[x] != chain[y])
        {
            if (depth[chain[x]] < depth[chain[y]])
                swap(x, y);
            ans = max(ans, query(1, 1, n, label[chain[x]], label[x]));
            x = dad[chain[x]];
        }
        if (depth[x] > depth[y])
            swap(x, y);
        cout << combine(ans, query(1, 1, n, label[x], label[y])) <<'\n';
    }
    return 0;
}