Cod sursa(job #3288082)

Utilizator adelinapetreAdelina Petre adelinapetre Data 20 martie 2025 14:39:07
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.6 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

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

const int Nmax = 1e5 + 1, Lmax = 17;

int v[Nmax], nod[Nmax], blift[Lmax][Nmax], aint[270000];//pt problema
int parent[Nmax], depth[Nmax];//pt arbore
int sus[Nmax], sz[Nmax], lant[Nmax], poz[Nmax]; //pt hld: lant[i] = in ce lant e nodul i, sz[i] = cate lanturi parcurg max in jos de la nodul i, sus[i] = capatul sus al lantului i
vector<int> g[Nmax];
int n, cntlant = 0;

void dfs(int node, int par)//impart nodurile pe lanturi
{
    parent[node] = par;
    depth[node] = depth[par] + 1;
    if (node != 1 && g[node].size() == 1)
    {
        lant[node] = ++cntlant;
        sz[lant[node]] = 1;
        return;
    }
    for (auto it : g[node])
        if (it != par)
            dfs(it, node);
    int maxx = 0, cnt = 0, l = 0;
    for (auto it : g[node])
        if (it != par)
        {
            if (sz[lant[it]] > maxx)
                maxx = sz[lant[it]], cnt = 1, l = lant[it];
            else if (sz[lant[it]] == 1)
                cnt++;
        }
    lant[node] = l;
    sz[lant[node]] = maxx;
    if (cnt > 1)
        sz[lant[node]]++;
}

void dfs2(int node, int par)//aflu cel mai de sus nod al unui lant
{
    if (sus[lant[node]] == 0)
        sus[lant[node]] = node;
    for (auto it : g[node])
        if (it != par)
            dfs2(it, node);
}

bool cmp(int a, int b)
{
    if (sus[lant[a]] != sus[lant[b]])
        return sus[lant[a]] < sus[lant[b]];
    return depth[a] < depth[b];
}

void binlift()
{
    for (int i = 1; i <= n; i++)
        blift[0][i] = parent[i];
    for (int j = 1; j< Lmax; j++)
        for (int i = 1; i <= n; i++)
            blift[j][i] = blift[j - 1][blift[j - 1][i]];
}

int getlca(int x, int y)
{
    //vreau depth[x] < depth[y] adk x mai sus ca y
    if (depth[x] > depth[y]) swap(x, y);
    for (int j = Lmax - 1; j >= 0; j--)
        if ((depth[y] - depth[x]) & (1 << j))
            y = blift[j][y];
    if (x == y)
        return x;
    for (int j = Lmax - 1; j >= 0; j--)
        if (blift[j][x] != blift[j][y])
        {
            x = blift[j][x];
            y = blift[j][y];
        }
    return blift[0][x];
}

void update(int nod, int st, int dr, int poz, int val)
{
    if (st > poz || dr < poz)
        return;
    if (st == dr && dr == poz)
    {
        aint[nod] = val;
        return;
    }
    int mid = (st + dr) / 2;
    update(nod * 2, st, mid, poz, val);
    update(nod * 2 + 1, mid + 1, dr, poz, val);
    aint[nod] = max(aint[nod * 2], aint[nod * 2 + 1]);
}

int query(int nod, int st, int dr, int qst, int qdr)
{
    if (qst > dr || qdr < st)
        return 0;
    if (qst <= st && dr <= qdr)
        return aint[nod];
    int mid = (st + dr) / 2;
    int l = query(nod * 2, st, mid, qst, qdr), r = query(nod * 2 + 1, mid + 1, dr, qst, qdr);
    return max(l, r);
}

int solve(int x, int y)
{
    int lca = getlca(x, y), ans = 0;
    //cout << x << " " << y << " " << lca << '\n';
    while (sus[lant[x]] != sus[lant[lca]])
    {
        ans = max(ans, query(1, 1, n, poz[sus[lant[x]]], poz[x]));
        x = sus[lant[x]];
        x = parent[x];
    }
    ans = max(ans, query(1, 1, n, min(poz[lca], poz[x]), max(poz[lca], poz[x])));
    while (sus[lant[y]] != sus[lant[lca]])
    {
        ans = max(ans, query(1, 1, n, poz[sus[lant[y]]], poz[y]));
        y = sus[lant[y]];
        y = parent[y];
    }
    ans = max(ans, query(1, 1, n, min(poz[lca], poz[y]), max(poz[lca], poz[y])));
    return ans;
}

int main()
{
    int x, y, q, tip;
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
        cin >> v[i];
    for (int i = 1; i < n; i++)
    {
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs(1, 0);
    dfs2(1, 0);
    binlift();
    /*for (int i = 1; i <= n; i++)
        cout << i << " " << lant[i] << '\n';
    cout << '\n';
    for (int i = 1; i <= cntlant; i++)
        cout << i << ": " << sus[i] << '\n';*/
    for (int i = 1; i <= n; i++)
        nod[i] = i;
    sort(nod + 1, nod + n + 1, cmp);
    //for (int i = 1; i <= n; i++)
        //cout << a[i] << " ";
    for (int i = 1; i <= n; i++)
        poz[nod[i]] = i;
    for (int i = 1; i <= n; i++)
        update(1, 1, n, poz[i], v[i]);
    while (q--)
    {
        cin >> tip >> x >> y;
        if (tip == 0)
        {
            //nodul x devine y
            update(1, 1, n, poz[x], y);
        }
        else
        {
            cout << solve(x, y) << '\n';
        }
    }
    return 0;
}