Cod sursa(job #3168616)

Utilizator _andrei4567Stan Andrei _andrei4567 Data 12 noiembrie 2023 20:26:19
Problema Heavy Path Decomposition Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.76 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");

const int N = 1e5;
int siz[N + 1], lant_node[N + 1], head_lant[N + 1], dep[N + 1], poz[N + 1], aux[N + 1], len_lant[N + 1], a[N + 1], dad[N + 1];

vector <int> g[N + 1], lant[N + 1];

int n, m, x, y, cer, nr_lant;

void dfs (int node, int tata)
{
    int frunza = 1, mx = -1, nod = 0;
    siz[node] = 1;
    dep[node] = 1;
    dad[node] = tata;
    for (auto it : g[node])
        if (it != tata)
        {
            frunza = 0;
            dep[it] = dep[node] + 1;
            dfs (it, node);
            siz[node] += siz[it];
            if (mx < siz[it])
                mx = siz[it], nod = it;
        }
    if (frunza)
    {
        ++nr_lant;
        lant_node[node] = nr_lant;
        head_lant[nr_lant] = dad[node];
        lant[nr_lant].push_back(node);
        return;
    }
    int which = lant_node[nod];
    head_lant[which] = dad[node];
    lant_node[node] = which;
    lant[which].push_back(node);
}

struct segtree
{
    vector <int> v;
    void build (int node, int l, int r)
    {
        if (l == r)
        {
            v[node] = aux[l];
            return;
        }
        int mid = (l + r) >> 1;
        build (node << 1, l, mid);
        build (node << 1 | 1, mid + 1, r);
        v[node] = max (v[node << 1], v[node << 1 | 1]);
    }
    void update (int node, int l, int r, int pos, int val)
    {
        if (l == r)
        {
            v[node] = val;
            return;
        }
        int mid = (l + r) >> 1;
        if (pos <= mid) update (node << 1, l, mid, pos, val);
        else update (node << 1 | 1, mid + 1, r, pos, val);
        v[node] = max (v[node << 1], v[node << 1 | 1]);
    }
    int query (int node, int l, int r, int st, int dr)
    {
        if (l >= st && r <= dr)
            return v[node];
        int mid = (l + r) >> 1;
        int a, b;
        a = b = 0;
        if (st <= mid) a = query (node << 1, l, mid, st, dr);
        if (dr > mid) b = query (node << 1 | 1, mid + 1, r, st, dr);
        return max (a, b);
    }
} arb[N + 1];

void build_segtree ()
{
    for (int i = 1; i <= nr_lant; ++i)
    {
        reverse (lant[i].begin(), lant[i].end());
        int start = 0;
        for (auto it : lant[i])
            poz[it] = ++start, aux[start] = a[it];
        len_lant[i] = start;
        arb[i].v.assign(start * 5, 0);
        arb[i].build(1, 1, start);
    }
}

int query_ans (int x, int y)
{
    int ans = 0, lant_x, lant_y;
    while (lant_node[x] != lant_node[y])
    {
        lant_x = lant_node[x];
        lant_y = lant_node[y];
        if (dep[head_lant[lant_x]] < dep[head_lant[lant_y]])
        {
            ans = max (ans, arb[lant_y].query (1, 1, len_lant[lant_y], 1, poz[y]));
            y = head_lant[lant_y];
        }
        else
        {
            ans = max (ans, arb[lant_x].query (1, 1, len_lant[lant_x], 1, poz[x]));
            x = head_lant[lant_x];
        }
    }
    lant_x = lant_node[x];
    lant_y = lant_node[y];
    ans = max (ans, arb[lant_x].query(1, 1, len_lant[lant_x], min (poz[x], poz[y]), max(poz[y], poz[x])));
    return ans;
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    for (int i = 1; i < n && cin >> x >> y; ++i)
        g[x].push_back(y), g[y].push_back(x);
    dfs (1, 0);
    build_segtree();
    for (int i = 1; i <= m; ++i)
    {
        cin >> cer >> x >> y;
        if (!cer)
        {
            int which = lant_node[x];
            arb[which].update (1, 1, len_lant[which], poz[x], y);
        }
        else
            cout << query_ans (x, y) << '\n';
    }
    return 0;
}