Cod sursa(job #2876996)

Utilizator beingsebiPopa Sebastian beingsebi Data 24 martie 2022 00:15:15
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.73 kb
#include <bits/stdc++.h>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");
// #define f cin
// #define g cout
const int nmax = 15e4;
int n, q, albl,
    vals[nmax],      // valorile initiale
    sz[nmax],        // dimensiunile subarborilor
    label[nmax],     // indicii in ordine buna pt aint
    invl[nmax],      // opusul lui label
    top[nmax],       // unde se termina lantul
    depth[nmax],     // distanta de la radacina
    pre[nmax];       // parintele nodului
vector<int> v[nmax]; // muchiile
void dfs_init(int, int);
void dfs_heavy(int, int);
class ST
{
    int arr[2 * nmax], size = 1;
    void build(int ac, int st, int dr)
    {
        if (dr - st == 1)
        {
            if (st == 0 || st > n)
                arr[ac] = INT_MIN;
            else
                arr[ac] = vals[invl[st]];
        }
        else
        {
            int mid = (st + dr) / 2;
            build(ac * 2 + 1, st, mid);
            build(ac * 2 + 2, mid, dr);
            arr[ac] = max(arr[ac * 2 + 1], arr[ac * 2 + 2]);
        }
    }
    void update(int ac, int st, int dr, int poz, int val)
    {
        if (dr - st == 1)
            arr[ac] = val;
        else
        {
            int mid = (st + dr) / 2;
            if (poz < mid)
                update(ac * 2 + 1, st, mid, poz, val);
            else
                update(ac * 2 + 2, mid, dr, poz, val);
            arr[ac] = max(arr[ac * 2 + 1], arr[ac * 2 + 2]);
        }
    }
    int query(int ac, int st, int dr, int l, int r)
    {
        if (st >= r || dr <= l)
            return INT_MIN;
        if (st >= l && dr <= r)
            return arr[ac];
        int mid = (st + dr) / 2;
        return max(query(ac * 2 + 1, st, mid, l, r), query(ac * 2 + 2, mid, dr, l, r));
    }

public:
    void init()
    {
        while (size <= n)
            size <<= 1;
        build(0, 0, size);
    }
    void update(int poz, int val)
    {
        update(0, 0, size, poz, val);
    }
    int query(int st, int dr)
    {
        return query(0, 0, size, st, dr + 1);
    }
} aint;
int query(int, int);
int32_t main()
{
    f >> n >> q;
    for (int i = 1; i <= n; i++)
        f >> vals[i];
    for (int i = 1, x, y; i < n; i++)
        f >> x >> y, v[x].push_back(y), v[y].push_back(x);
    dfs_init(1, 0);
    dfs_heavy(1, 0);
    aint.init();
    // for (int i = 1; i <= n; i++)
    //     g << top[i] << '\n';
    for (int a, b, c; q; q--)
    {
        f >> c >> a >> b;
        if (c == 0)
            aint.update(label[a], b);
        else
            g << query(a, b) << '\n';
    }
    return 0;
}
int query(int a, int b)
{
    // cout << a << " " << b << '\n';
    if (label[a] > label[b])
        swap(a, b);
    if (top[a] == top[b])
    {
        return aint.query(label[a], label[b]);
    }
    if (depth[top[a]] > depth[top[b]])
    {
        int new_a = pre[top[a]];
        return max(aint.query(label[top[a]], label[a]), query(new_a, b));
    }
    int new_b = pre[top[b]];
    return max(aint.query(label[top[b]], label[b]), query(new_b, a));
}
void dfs_init(int ac, int par)
{
    pre[ac] = par;
    depth[ac] = depth[par] + 1;
    top[ac] = ac;
    sz[ac] = 1;
    for (const int &i : v[ac])
        if (i != par)
            dfs_init(i, ac), sz[ac] += sz[i];
}
void dfs_heavy(int ac, int par)
{
    label[ac] = ++albl;
    invl[albl] = ac;
    int maxim = -1, ind = -1;
    for (const int &i : v[ac])
        if (i != par && sz[i] > maxim)
            maxim = sz[i], ind = i;
    if (maxim == -1)
        return;
    top[ind] = top[ac];
    dfs_heavy(ind, ac);
    for (const int &i : v[ac])
        if (i != par && i != ind)
            dfs_heavy(i, ac);
}