Cod sursa(job #2939126)

Utilizator CristeaCristianCristea Cristian CristeaCristian Data 13 noiembrie 2022 01:12:59
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.95 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
const int NMAX = 100005;
long long tree[4 * NMAX], st[NMAX], cost[NMAX], sz[NMAX], hindex[NMAX], heavyhead[NMAX], heavychild[NMAX], depth[NMAX], f[NMAX], parent[NMAX], cnt, n;
vector<vector<int>> v;
void build(int k, int l, int r)
{
    if(l > r)
        return;
    if(l == r)
    {
        tree[k] = st[l];
        return;
    }
    build(2*k, l, (l+r)/2);
    build(2*k+1, (l+r)/2+1, r);
    tree[k] = max(tree[2*k], tree[2*k+1]);
}
void update(int pos, int val, int k, int l, int r)
{
    if(pos < l || pos > r || l > r)
        return;
    if(l == r && l == pos)
    {
        tree[k] = val;
        return;
    }
    update(pos, val, 2*k, l, (l+r)/2);
    update(pos, val, 2*k+1, (l+r)/2+1, r);
    tree[k] = max(tree[2*k], tree[2*k+1]);
}
long long query(int i, int j, int k, int l, int r)
{
    if(l > r)
        return -1;
    if(r < i || j < l)
        return -1;
    if(i <= l && r <= j)
        return tree[k];
    return max(query(i, j, 2*k, l, (l+r)/2), query(i, j, 2*k+1, (l+r)/2+1, r));
}
void dfs(int u)
{
    heavychild[u] = 0;
    sz[u] = cost[u];
    for(auto it: v[u])
    {
        depth[it] = depth[u] + 1;
        dfs(it);
        sz[u] += sz[it];
        if(sz[it] > sz[heavychild[u]])
            heavychild[u] = it;
    }
}
void dfsHeavyFirst(int u)
{
    hindex[u] = ++cnt;
    st[cnt] = cost[u];
    if(heavychild[u] != 0)
    {
        heavyhead[heavychild[u]] = heavyhead[u];
        dfsHeavyFirst(heavychild[u]);
    }
    for(auto it: v[u])
    {
        if(it != heavychild[u])
        {
            heavyhead[it] = it;
            dfsHeavyFirst(it);
        }
    }
}
long long maxOnPath(int u, int v)
{
    if(heavyhead[u] == heavyhead[v])
    {
        if(depth[u] < depth[v])
            return query(hindex[u], hindex[v], 1, 1, n);
        else
            return query(hindex[v], hindex[u], 1, 1, n);
    }
    else if(depth[heavyhead[u]] < depth[heavyhead[v]])
        return max(maxOnPath(u, parent[heavyhead[v]]), query(hindex[heavyhead[v]], hindex[v], 1, 1, n));
    else
        return max(maxOnPath(parent[heavyhead[u]], v), query(hindex[heavyhead[u]], hindex[u], 1, 1, n));
}
int main()
{
    int q, i, a, b, root, op;
    cin >> n >> q;
    for(i = 1; i <= n; i++)
        cin >> cost[i];
    v.resize(n+1);
    for(i = 1; i < n; i++)
    {
        cin >> a >> b;
        parent[b] = a;
        v[a].push_back(b);
        f[b] = 1;
    }
    for(i = 1; i <= n; i++)
        if(!f[i])
            root = i;
    depth[root] = 1;
    dfs(root);
    heavyhead[root] = root;
    dfsHeavyFirst(root);
    build(1, 1, n);
    while(q--)
    {
        cin >> op >> a >> b;
        if(op == 0)
            update(hindex[a], b, 1, 1, n);
        else
            cout << maxOnPath(a, b) << '\n';
    }
    return 0;
}