Cod sursa(job #3128872)

Utilizator RobertAcAcatrinei Robert-Marian RobertAc Data 11 mai 2023 11:10:56
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.01 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;

int n, m;
int v[nmax];
int lIndex[nmax];
int ppoz[nmax];
int depth[nmax];
int parent[lgmax][nmax];

struct aint
{
    int val;
    aint *pst, *pdr;
    aint(int val = 0) : val(val)
    {
        pst = pdr = nullptr;
    }
    aint *getSt()
    {
        if (pst == nullptr)
            pst = new aint();
        return pst;
    }
    aint *getDr()
    {
        if (pdr == nullptr)
            pdr = new aint();
        return pdr;
    }
    int stVal()
    {
        if (pst == nullptr)
            return 0;
        return pst->val;
    }
    int drVal()
    {
        if (pdr == nullptr)
            return 0;
        return pdr->val;
    }
    void update(int poz, int vall, int st, int dr)
    {
        if (st == dr)
        {
            val = vall;
        }
        else
        {
            int mid = (st + dr) / 2;
            if (poz <= mid)
            {
                getSt()->update(poz, vall, st, mid);
            }
            else
            {
                getDr()->update(poz, vall, mid + 1, dr);
            }
            val = max(stVal(), drVal());
        }
    }
    int query(int l, int r, int st, int dr, int nod = 1)
    {
        if (this == nullptr)
            return 0;
        if (l == st && r == dr)
        {
            return val;
        }
        else
        {
            int mid = (st + dr) / 2;
            if (r <= mid)
            {
                return pst->query(l, r, st, mid);
            }
            else if (mid < l)
            {
                return pdr->query(l, r, mid + 1, dr);
            }
            else
            {
                return max(pst->query(l, mid, st, mid), pdr->query(mid + 1, r, mid + 1, dr));
            }
        }
    }
    void debug(int st, int dr)
    {
        if (this == nullptr)
            cerr << 0 << '\n';
        else
        {
            cerr << st << ' ' << dr << ' ' << val << '\n';
            pst->debug(st, (st + dr) / 2);
            pdr->debug((st + dr) / 2 + 1, dr);
        }
    }
};

struct Path
{
    int size, p;
    aint *arb;
    vector<int> vec;
    Path(int size, int p, vector<int> v) : size(size), p(p)
    {
        reverse(v.begin(), v.end());
        vec = v;
        for (int ind = 0; ind < vec.size(); ind++)
        {
            ppoz[vec[ind]] = ind;
        }
        arb = new aint();
    }
    void update(int ind)
    {
        arb->update(ppoz[ind], v[ind], 0, size - 1);
    }
    int query(int l, int r)
    {
        return arb->query(l, r, 0, size - 1);
    }
    int firstElem()
    {
        return vec[0];
    }
    void debug()
    {
        for (auto i : vec)
        {
            cerr << i << ' ';
        }
        cerr << '\n';
        for (auto i : vec)
        {
            cerr << v[i] << ' ';
        }
        cerr << '\n';
        arb->debug(0, size - 1);
    }
};

vector<int> adj[nmax];
vector<Path> paths;

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));
            for (auto j : i)
            {
                lIndex[j] = paths.size() - 1;
            }
        }
    }
    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)
{
    int ans = 0;
    while (1)
    {
        if (depth[paths[lIndex[jos]].firstElem()] <= depth[sus])
        {
            ans = max(ans, paths[lIndex[jos]].query(ppoz[sus], ppoz[jos]));
            break;
        }
        else
        {
            ans = max(ans, paths[lIndex[jos]].query(0, ppoz[jos]));
            jos = paths[lIndex[jos]].p;
        }
    }
    return ans;
}

void solve()
{
    for (int i = 1; i <= n; i++)
    {
        paths[lIndex[i]].update(i);
    }
    for (int i = 0; i < m; i++)
    {
        int t, x, y;
        in >> t >> x >> y;
        if (t == 0)
        {
            v[x] = y;
            paths[lIndex[x]].update(x);
        }
        else
        {
            int p = lca(x, y);
            out << max(q(p, x), q(p, y)) << '\n';
        }
    }
}

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