Cod sursa(job #3201368)

Utilizator Raul_AArdelean Raul Raul_A Data 7 februarie 2024 19:50:13
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.88 kb
#include <bits/stdc++.h>
#define eb emplace_back
#define ll long long
#define pii pair<int, int>
#define pli pair<ll, int>
#define pcc pair<char, char>
#define tli tuple<ll, int, int>
using namespace std;

const string fn("heavypath");

ifstream in(fn + ".in");
ofstream out(fn + ".out");

#define cin in
#define cout out

const int MAX = 1e5;

int n, q, val[MAX + 5], niv[MAX + 5], w[MAX + 5];
int nrL, L[MAX + 5], Lfather[MAX + 5], Lniv[MAX + 5], Ldecal[MAX + 5];
int Tree[4 * MAX + 5];
vector<int> g[MAX + 5], Lant[MAX + 5];
bitset<MAX + 5> viz;

void dfs(int node)
{
    viz[node] = 1;
    w[node] = 1;
    bool leaf = 1;
    int maxl = -1;

    for (auto x : g[node])
    {
        if (viz[x])
            continue;
        niv[x] = niv[node] + 1;
        leaf = 0;
        dfs(x);
        w[node] += w[x];
        if (maxl == -1)
            maxl = x;
        else if (w[maxl] < w[x])
            maxl = x;
    }

    if (leaf)
    {
        nrL++;
        L[node] = nrL;
        Lant[nrL].eb(node);
        return;
    }
    L[node] = L[maxl];
    Lant[L[node]].eb(node);

    for (auto x : g[node])
    {
        if (x == maxl or niv[x] < niv[node])
            continue;
        Lfather[L[x]] = node;
        Lniv[L[x]] = niv[node];
    }
}

void build(int node, int l, int r, int decal, int pozl)
{
    if (l == r)
        Tree[node + decal] = val[Lant[pozl][l - 1]];
    else
    {
        int m = l + r >> 1;
        build(node << 1, l, m, decal, pozl);
        build(node << 1 | 1, m + 1, r, decal, pozl);

        Tree[node + decal] = max(Tree[(node << 1) + decal], Tree[(node << 1 | 1) + decal]);
    }
}

void update(int node, int l, int r, int target, int decal, int value)
{
    if (l == r)
    {
        Tree[node + decal] = value;
    }
    else
    {
        int m = l + r >> 1;
        if (target <= m)
            update(node << 1, l, m, target, decal, value);
        else
            update(node << 1 | 1, m + 1, r, target, decal, value);

        Tree[node + decal] = max(Tree[(node << 1) + decal], Tree[(node << 1 | 1) + decal]);
    }
}

int query(int node, int l, int r, int a, int b, int decal)
{
    if (a <= l and r <= b)
        return Tree[node + decal];
    else
    {
        int m = l + r >> 1;
        int l_val = INT_MIN, r_val = INT_MIN;

        if (a <= m)
            l_val = query(node << 1, l, m, a, b, decal);
        if (b > m)
            r_val = query(node << 1 | 1, m + 1, r, a, b, decal);

        return max(l_val, r_val);
    }
}

void make_paths()
{
    niv[1] = 1;
    dfs(1);

    for (int i = 1; i <= nrL; i++)
    {
        reverse(Lant[i].begin(), Lant[i].end());
        if (i != 1)
            Ldecal[i] = Ldecal[i - 1] + Lant[i].size() * 4;
        build(1, 1, Lant[i].size(), Ldecal[i], i);
    }
}

void solve()
{
    int t, x, y;
    cin >> t >> x >> y;

    if (t == 0)
    {
        update(1, 1, Lant[L[x]].size(), niv[x] - Lniv[L[x]], Ldecal[L[x]], y);
    }
    else
    {
        int ans = INT_MIN;
        while (1)
        {
            if (L[x] == L[y])
            {
                if (niv[x] > niv[y])
                    swap(x, y);
                ans = max(ans, query(1, 1, Lant[L[x]].size(), niv[x] - Lniv[L[x]], niv[y] - Lniv[L[y]], Ldecal[L[x]]));
                break;
            }
            if (Lniv[L[x]] < Lniv[L[y]])
                swap(x, y);

            ans = max(ans, query(1, 1, Lant[L[x]].size(), 1, niv[x] - Lniv[L[x]], Ldecal[L[x]]));
            x = Lfather[L[x]];
        }
        cout << ans << '\n';
    }
    //cout << -1;
}

int main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
        cin >> val[i];
    for (int i = 1, x, y; i < n; i++)
    {
        cin >> x >> y;
        g[x].eb(y);
        g[y].eb(x);
    }

    make_paths();
    while (q--)
        solve();
    return 0;
}