Cod sursa(job #3226457)

Utilizator IvanAndreiIvan Andrei IvanAndrei Data 21 aprilie 2024 14:48:08
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.85 kb
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

#pragma GCC optimize ("O1")
#pragma GCC optimize ("O2")
#pragma GCC optimize ("O3")
#pragma GCC optimize ("Ofast")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target ("avx2")

using namespace std;
using namespace __gnu_pbds;

#define ordered_set tree <long long, null_type, less<long long>, rb_tree_tag, tree_order_statistics_node_update>
#define lsb(x)(x & (-x))

const long long max_size = 1e5 + 20;

int t[max_size], cap[max_size], sz[max_size], aint[4 * max_size], v[max_size], lin[max_size], timp, lvl[max_size], n, pos[max_size];
vector <int> mc[max_size];

void dfssz (int nod, int par)
{
    t[nod] = par;
    cap[nod] = nod;
    lvl[nod] = lvl[par] + 1;
    for (auto f : mc[nod])
    {
        if (f == par)
        {
            continue;
        }
        dfssz(f, nod);
        sz[nod] += sz[f];
    }
    sz[nod]++;
}

void dfsh (int nod, int par)
{
    ++timp;
    lin[timp] = nod;
    pos[nod] = timp;
    int mx = -1, idx = 0;
    for (auto f : mc[nod])
    {
        if (f == par)
        {
            continue;
        }
        if (sz[f] > mx)
        {
            mx = sz[f];
            idx = f;
        }
    }
    if (mx == -1)
    {
        return;
    }
    cap[idx] = cap[nod];
    dfsh(idx, nod);
    for (auto f : mc[nod])
    {
        if (f == par || f == idx)
        {
            continue;
        }
        dfsh(f, nod);
    }
}

void init (int l, int r, int nod)
{
    if (l == r)
    {
        aint[nod] = v[lin[l]];
        return;
    }
    int m = (l + r) / 2;
    init(l, m, 2 * nod);
    init(m + 1, r, 2 * nod + 1);
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}

void upd (int l, int r, int poz, int val, int nod)
{
    if (l == r)
    {
        aint[nod] = val;
        return;
    }
    int m = (l + r) / 2;
    if (poz <= m)
    {
        upd(l, m, poz, val, 2 * nod);
    }
    else
    {
        upd(m + 1, r, poz, val, 2 * nod + 1);
    }
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}

int queryaint (int l, int r, int st, int dr, int nod)
{
    if (st <= l && r <= dr)
    {
        return aint[nod];
    }
    int m = (l + r) / 2, ans1 = 0, ans2 = 0;
    if (st <= m)
    {
        ans1 = queryaint(l, m, st, dr, 2 * nod);
    }
    if (dr > m)
    {
        ans2 = queryaint(m + 1, r, st, dr, 2 * nod + 1);
    }
    return max(ans1, ans2);
}

int queryheavy (int x, int y)
{
    if (cap[x] == cap[y])
    {
        x = pos[x];
        y = pos[y];
        if (x > y)
        {
            swap(x, y);
        }
        return queryaint(1, n, x, y, 1);
    }
    if (lvl[cap[x]] < lvl[cap[y]])
    {
        swap(x, y);
    }
    return max(queryheavy(y, t[cap[x]]), queryaint(1, n, pos[cap[x]], pos[x], 1));
}

void solve ()
{
    int q;
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
    {
        cin >> v[i];
    }
    for (int i = 1; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        mc[x].push_back(y);
        mc[y].push_back(x);
    }
    dfssz(1, 0);
    dfsh(1, 0);
    init(1, n, 1);
    while (q--)
    {
        int op, x, y;
        cin >> op >> x >> y;
        if (op == 0)
        {
            upd(1, n, pos[x], y, 1);
        }
        else
        {
            cout << queryheavy(x, y) << '\n';
        }
    }
    cout << '\n';
}

signed main ()
{
#ifdef LOCAL
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#else
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
#endif // LOCAL
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    long long tt;
    //cin >> tt;
    tt = 1;
    while (tt--)
    {
        solve();
    }
    return 0;
}