Cod sursa(job #3224414)

Utilizator andreiiorgulescuandrei iorgulescu andreiiorgulescu Data 15 aprilie 2024 12:37:44
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.85 kb
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2")

using namespace std;

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

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

void dfs(int nod)
{
    sz[nod] = 1;
    for (auto vecin : g[nod])
    {
        if (vecin != t[nod])
        {
            t[vecin] = nod;
            f[nod].push_back(vecin);
            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 (!f[nod].empty())
    {
        isheavy[heavyson[nod]] = true;
        dfs2(heavyson[nod]);
        for (auto vecin : f[nod])
        {
            if (vecin != heavyson[nod])
                dfs2(vecin);
        }
    }
}

int bl[20][200005];

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

int aint[800005];

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 <= 17; 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 == 1)
            update(1,1,n,pos[x],y);
        else
        {
            int l = lca(x,y);
            out << max(getans(x,l),getans(y,l)) << '\n';
        }
    }
    return 0;
}