Cod sursa(job #3224420)

Utilizator andreiiorgulescuandrei iorgulescu andreiiorgulescu Data 15 aprilie 2024 12:45:43
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.74 kb
#include <bits/stdc++.h>

using namespace std;

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

int n,q,v[100005];
vector<int> g[100005];
int t[100005],h[100005],sz[100005];
int szheavy[100005],heavyson[100005];
int ord[100005],pos[100005],curord;
int vord[100005];
bool isheavy[100005];
int lastheavy[100005];

void dfs(int nod)
{
    sz[nod] = 1;
    for (auto vecin : g[nod])
    {
        if (vecin != t[nod])
        {
            t[vecin] = nod;
            h[vecin] = 1 + h[nod];
            dfs(vecin);
            sz[nod] += sz[vecin];
            if (sz[vecin] > szheavy[nod])
            {
                szheavy[nod] = sz[vecin];
                heavyson[nod] = vecin;
            }
        }
    }
}

void dfs2(int nod)
{
    if (!isheavy[nod])
        lastheavy[nod] = nod;
    else
        lastheavy[nod] = lastheavy[t[nod]];
    ord[++curord] = nod;
    pos[nod] = curord;
    if (g[nod].size() >= 2 or t[nod] == 0)
    {
        isheavy[heavyson[nod]] = true;
        dfs2(heavyson[nod]);
        for (auto vecin : g[nod])
        {
            if (vecin != heavyson[nod] and vecin != t[nod])
                dfs2(vecin);
        }
    }
}

int bl[17][100005];

int lca(int x,int y)
{
    if (h[x] < h[y])
        swap(x,y);
    for (int pas = 16; pas >= 0; pas--)
        if (h[x] - (1 << pas) >= h[y])
            x = bl[pas][x];
    if (x == y)
        return x;
    for (int pas = 16; pas >= 0; pas--)
        if (bl[pas][x] != bl[pas][y])
            x = bl[pas][x],y = bl[pas][y];
    return t[x];
}

int aint[400005];

void build(int nod,int l,int r)
{
    if (l == r)
        aint[nod] = vord[l];
    else
    {
        int mij = (l + r) / 2;
        build(2 * nod,l,mij);
        build(2 * nod + 1,mij + 1,r);
        aint[nod] = max(aint[2 * nod],aint[2 * nod + 1]);
    }
}

void update(int nod,int l,int r,int pos,int val)
{
    if (l == r)
        aint[nod] = val;
    else
    {
        int mij = (l + r) / 2;
        if (pos <= mij)
            update(2 * nod,l,mij,pos,val);
        else
            update(2 * nod + 1,mij + 1,r,pos,val);
        aint[nod] = max(aint[2 * nod],aint[2 * nod + 1]);
    }
}

int query(int nod,int l,int r,int st,int dr)
{
    if (dr < l or r < st)
        return 0;
    if (st <= l and r <= dr)
        return aint[nod];
    int mij = (l + r) / 2;
    return max(query(2 * nod,l,mij,st,dr),query(2 * nod + 1,mij + 1,r,st,dr));
}

int getans(int x,int y)
{
    int ans = 0;
    while (h[x] >= h[y])
    {
        int urm = lastheavy[x];
        if (h[urm] < h[y])
            urm = y;
        ans = max(ans,query(1,1,n,pos[urm],pos[urm] + h[x] - h[urm]));
        x = t[urm];
    }
    return ans;
}

int main()
{
    in >> n >> q;
    for (int i = 1; i <= n; i++)
        in >> v[i];
    for (int i = 1; i < n; i++)
    {
        int x,y;
        in >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    h[0] = -1;
    dfs(1);
    dfs2(1);
    /*for (int i = 1; i <= n; i++)
        cout << pos[i] << ' ';
    cout << endl;*/
    /*for (int i = 1; i <= curord; i++)
        cout << ord[i] << ' ';
    cout << endl;*/
    for (int i = 1; i <= n; i++)
        bl[0][i] = t[i];
    for (int j = 1; j <= 16; j++)
        for (int i = 1; i <= n; i++)
            bl[j][i] = bl[j - 1][bl[j - 1][i]];
    for (int i = 1; i <= n; i++)
        vord[pos[i]] = v[i];
    build(1,1,n);
    for (int i = 1; i <= q; i++)
    {
        int tip,x,y;
        in >> tip >> x >> y;
        if (tip == 0)
            update(1,1,n,pos[x],y);
        else
        {
            int l = lca(x,y);
            out << max(getans(x,l),getans(y,l)) << '\n';
        }
    }
    return 0;
}