Cod sursa(job #3308817)

Utilizator andrei.nNemtisor Andrei andrei.n Data 28 august 2025 15:46:12
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.73 kb
#include <bits/stdc++.h>

using namespace std;

const int INF = 2100000000;
int val[100005];
vector<int> v[100005];
int depth[100005];
int in[100005], out[100005], t;
int up[18][100005];
int down[100005];
int heavy[100005];
vector<vector<int>> aint;
int len[100005];
int which[100005];
int pos[100005];
int last[100005];

void dfs(int node)
{
    in[node] = ++t;
    down[node] = 1;
    for(auto son : v[node])
        if(!depth[son])
        {
            depth[son] = depth[node] + 1;
            dfs(son);
            down[node] += down[son];
        }
        else up[0][node] = son;
    out[node] = ++t;
}

void updateAINT(int idx, int st, int dr, int pos, int p, int x)
{
    if(st == dr)
        aint[idx][pos] = x;
    else
    {
        int mij = (st+dr>>1);
        if(p <= mij) updateAINT(idx, st, mij, pos<<1, p, x);
        else updateAINT(idx, mij+1, dr, pos<<1|1, p, x);
        aint[idx][pos] = max(aint[idx][pos<<1], aint[idx][pos<<1|1]);
    }
}

void queryAINT(int idx, int st, int dr, int pos, int a, int b, int &res)
{
    if(a <= st && dr <= b)
        res = max(res, aint[idx][pos]);
    else
    {
        int mij = (st+dr>>1);
        if(a <= mij) queryAINT(idx, st, mij, pos<<1, a, b, res);
        if(b > mij) queryAINT(idx, mij+1, dr, pos<<1|1, a, b, res);
    }
}

inline bool ascensor(int a, int b)
{
    return in[a] <= in[b] && out[b] <= out[a];
}

int lca(int a, int b)
{
    if(depth[a] > depth[b]) swap(a, b);
    if(ascensor(a, b)) return a;
    for(int i=17; i>=0; --i)
        if(!ascensor(up[i][a], up[i][b]))
        {
            a = up[i][a];
            b = up[i][b];
        }
    return up[0][a];
}

void update(int node, int x)
{
    val[node] = x;
    updateAINT(which[node], 1, len[which[node]], 1, pos[node], x);
}

int query(int a, int b)
{
    int res = 0;
    while(which[a] != which[b])
    {
        queryAINT(which[a], 1, len[which[a]], 1, pos[a], len[which[a]], res);
        a = up[0][last[which[a]]];
    }
    queryAINT(which[a], 1, len[which[a]], 1, pos[a], pos[b], res);
    return res;
}

signed main()
{
    ifstream fin ("heavypath.in");
    ofstream fout ("heavypath.out");
    ios::sync_with_stdio(false); fin.tie(0); fout.tie(0);
    int n, q; fin>>n>>q;
    for(int i=1; i<=n; ++i)
    {
        fin>>val[i];
        heavy[i] = -1;
        which[i] = -1;
    }
    for(int i=1; i<n; ++i)
    {
        int a, b; fin>>a>>b;
        v[a].push_back(b);
        v[b].push_back(a);
    }
    depth[1] = 1;
    in[0] = 0; out[0] = INF;
    dfs(1);
    for(int i=1; i<=n; ++i)
        for(int j=0; j<v[i].size(); ++j)
            if(v[i][j] != up[0][i] && (heavy[i] == -1 || down[v[i][j]] > down[v[i][heavy[i]]]))
                heavy[i] = j;
    for(int i=2; i<=n; ++i)
    {
        if(v[i].size() != 1) continue;
        which[i] = aint.size();
        len[which[i]] = 1;
        last[which[i]] = i;
        pos[i] = 1;
        aint.push_back(vector<int>());
        int node = up[0][i];
        while(node != 0 && which[v[node][heavy[node]]] == which[i])
        {
            which[node] = which[i];
            pos[node] = pos[v[node][heavy[node]]] + 1;
            ++len[which[node]];
            last[which[node]] = node;
            node = up[0][node];
        }
        aint[which[i]].assign(4 * len[which[i]], 0);
    }
    for(int i=1; i<18; ++i)
        for(int j=1; j<=n; ++j)
            up[i][j] = up[i-1][up[i-1][j]];
    for(int i=1; i<=n; ++i)
        update(i, val[i]);
    while(q--)
    {
        int t, a, b; fin>>t>>a>>b;
        if(t == 0)
            update(a, b);
        else
            fout << max(query(a, lca(a, b)), query(b, lca(a, b))) << '\n';
    }
    return 0;
}