Cod sursa(job #3192074)

Utilizator RobertAcAcatrinei Robert-Marian RobertAc Data 11 ianuarie 2024 13:10:50
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.89 kb
#include <bits/stdc++.h>
#ifdef LOCAL
#define in cin
#define out cout
#endif

using namespace std;

#ifndef LOCAL
ifstream in("heavypath.in");
ofstream out("heavypath.out");
#endif

const int nmax = 1e5 + 5e0;

int n, m;

int v[nmax];

vector<int> adj[nmax];
int parent[nmax];
int depth[nmax];

int aint[4 * nmax];
int aintIndex[nmax];

vector<int> paths;
int pIndex[nmax];
bool pathEnd[nmax];
int psize[nmax];
int pind;

struct query
{
    int t, x, y;
    query(int t = 0, int x = 0, int y = 0) : t(t), x(x), y(y) {}
} queries[nmax];

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

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

int ind = 1;

void dfs(int nod = 1, int p = 0, int dep = 0)
{
    parent[nod] = p;
    psize[nod] = 1;
    depth[nod] = dep;
    int maxx = 0;
    for (auto i : adj[nod])
    {
        if (i != p)
        {
            dfs(i, nod, dep + 1);
            psize[nod]+=psize[i];
            maxx = max(maxx, psize[i]);
        }
    }
    bool found = 0;
    for (auto i : adj[nod])
    {
        if (psize[i] == maxx && !found && i != p)
        {
            found = 1;
        }
        else if (i != p)
        {
            pathEnd[i] = 1;
        }
    }
}

void readInput()
{
    in >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        in >> v[i];
    }
    for (int i = 1; i < n; i++)
    {
        int a, b;
        in >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    for (int i = 0; i < m; i++)
    {
        in >> queries[i].t >> queries[i].x >> queries[i].y;
    }
    pathEnd[1] = 1;
}

int q(int x, int y)
{
    int ans = 0;
    while (1)
    {
        auto px = paths[pIndex[x]];
        auto py = paths[pIndex[y]];
        if (px == py)
        {
            if (depth[x] > depth[y])
            {
                x ^= y;
                y ^= x;
                x ^= y;
            }
            ans = max(ans, query(aintIndex[y], aintIndex[x]));
            break;
        }
        else
        {
            if (depth[px] < depth[py])
            {
                x ^= y;
                y ^= x;
                x ^= y;
                px ^= py;
                py ^= px;
                px ^= py;
            }
            ans = max(ans, query(aintIndex[x], aintIndex[px]));
            x = parent[px];
        }
    }
    return ans;
}

void solve()
{
    for (int i = 1; i <= n; i++)
    {
        update(aintIndex[i], v[i]);
    }
    for (int i = 0; i < m; i++)
    {
        int t = queries[i].t, x = queries[i].x, y = queries[i].y;
        if (t == 0)
        {
            v[x] = y;
            update(aintIndex[x], y);
        }
        else
        {
            out << q(x, y) << '\n';
        }
    }
}

void calcPath(int node)
{
    aintIndex[node] = ind++;
    pIndex[node] = pind;
    if (pathEnd[node])
    {
        paths.push_back(node);
    }
    else
    {
        calcPath(parent[node]);
    }
}

void doPaths()
{
    for (int i = 1; i <= n; i++)
    {
        if (adj[i].size() - (parent[i] != 0) == 0)
        {
            calcPath(i);
            pind++;
        }
    }
}

int main()
{
    readInput();
    dfs();
    doPaths();
    solve();
}