Cod sursa(job #3129615)

Utilizator RobertAcAcatrinei Robert-Marian RobertAc Data 15 mai 2023 09:54:08
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.7 kb
#include <bits/stdc++.h>
// #define in cin
// #define out cout

using namespace std;

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

const int nmax = 1e5 + 5e0;
const int lgmax = 18;

struct Path
{
    int size, p;
    int f;
    Path(int size, int p, int f) : size(size), p(p), f(f)
    {
    }
    int firstElem()
    {
        return f;
    }
};

int n, m;
int v[nmax];
int depth[nmax];
int parent[lgmax][nmax];
int pIndex[nmax];
vector<int> adj[nmax];
vector<Path> paths;
int aint[3 * nmax];
int aintIndex[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;

vector<int> dfs(int nod = 1, int p = 0, int dep = 0)
{
    depth[nod] = dep;
    parent[0][nod] = p;
    for (int i = 1; i < lgmax; i++)
    {
        parent[i][nod] = parent[i - 1][parent[i - 1][nod]];
    }
    vector<int> path;
    vector<vector<int>> tmm;
    int maxx = 0;
    for (auto i : adj[nod])
    {
        if (i != p)
        {
            auto tm = dfs(i, nod, dep + 1);
            tmm.push_back(tm);
            maxx = max(maxx, (int)tm.size());
        }
    }
    bool found = 0;
    for (auto i : tmm)
    {
        if (i.size() == maxx && found == 0)
        {
            path = i;
            found = 1;
        }
        else
        {
            paths.push_back(Path(i.size(), nod, i.back()));
            for (auto j : i)
            {
                pIndex[j] = paths.size() - 1;
                aintIndex[j] = ind++;
            }
        }
    }
    path.push_back(nod);
    return path;
}

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);
    }
}

int lca(const int a, const int b)
{
    int ta = a, tb = b;
    if (depth[a] > depth[b])
    {
        int diff = depth[a] - depth[b];
        for (int i = 0, bit = 1; i < lgmax; i++, bit <<= 1)
        {
            if (diff & bit)
            {
                diff -= bit;
                ta = parent[i][ta];
            }
        }
    }
    else if (depth[b] > depth[a])
    {
        int diff = depth[b] - depth[b];
        for (int i = 0, bit = 1; i < lgmax; i++, bit <<= 1)
        {
            if (diff && bit)
            {
                diff -= bit;
                tb = parent[i][tb];
            }
        }
    }
    if (ta == tb)
        return ta;

    for (int i = 0; i < lgmax; i++)
    {
        if (parent[i][ta] != parent[i][tb])
        {
            ta = parent[i][ta];
            tb = parent[i][tb];
        }
    }
    return parent[0][ta];
}

int q(const int sus, int jos)
{
    //cerr << sus << '\n';
    int ans = 0;
    while (1)
    {
        if (depth[paths[pIndex[jos]].firstElem()] <= depth[sus])
        {
            //cerr << sus << ' ' << jos << '\n';
            ans = max(ans, query(aintIndex[jos], aintIndex[sus]));
            //cerr << "->" << ans << '\n';
            break;
        }
        else
        {
            //cerr << paths[pIndex[jos]].firstElem() << ' ' << jos << '\n';
            ans = max(ans, query(aintIndex[jos], aintIndex[paths[pIndex[jos]].firstElem()]));
            jos = paths[pIndex[jos]].p;
            //cerr << "->" << ans << '\n';
        }
    }
    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, x, y;
        in >> t >> x >> y;
        if (t == 0)
        {
            v[x] = y;
            update(aintIndex[x], y);
        }
        else
        {
            int p = lca(x, y);
            //out << max(q(p, x), q(p, y)) << '\n';
        }
    }
}

int main()
{
    readInput();
    auto i = dfs();
    paths.push_back(Path(i.size(), 0, i.back()));
    for (auto j : i)
    {
        pIndex[j] = paths.size() - 1;
        aintIndex[j] = ind++;
    }
    solve();
}