Cod sursa(job #3204605)

Utilizator raileanu-alin-gabrielRaileanu Alin-Gabriel raileanu-alin-gabriel Data 17 februarie 2024 10:24:02
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.98 kb
#include <fstream>
#include <vector>
#include <algorithm>
const int NMAX=100005;

using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

void dfs(int, int);
void heavy_light_decomp();
void build(int, int, int);
void update(int, int, int, int, int);
int query(int, int, int, int, int);
void update_hld(int, int);
int query_hld(int, int);

vector <int> v[NMAX], path[NMAX];
int a[NMAX], poz[NMAX], p[NMAX], aint[4*NMAX];
int lin[NMAX], sz[NMAX], niv[NMAX], nrp[NMAX];
int pn, n, q;

int main()
{
    int i, tip, aa, b;
    fin>>n>>q;
    for(i=1; i<=n; i++) fin>>a[i];
    for(i=1; i<n; i++)
    {
        fin>>aa>>b;
        v[aa].push_back(b);
        v[b].push_back(aa);
    }
    heavy_light_decomp();
    for(i=1; i<=q; i++)
    {
        fin>>tip>>aa>>b;
        if(tip==0) update_hld(aa, b);
        else fout<<query_hld(aa, b)<<'\n';
    }
    return 0;
}

void update_hld(int nod, int val)
{
    update(1, 1, n, poz[nod], val);
}

int query_hld(int a, int b)
{
    int maxim=0;
    while(true)
    {
        if(niv[a]>niv[b]) swap(a, b);
        if(nrp[a]==nrp[b])
        {
            maxim=max(maxim, query(1, 1, n, poz[a], poz[b]));
            return maxim;
        }
        if(niv[path[nrp[a]][0]]>niv[path[nrp[b]][0]]) swap(a, b);
        maxim=max(maxim, query(1, 1, n, poz[path[nrp[b]][0]], poz[b]));
        b=p[path[nrp[b]][0]];
    }
    return maxim;
}

void heavy_light_decomp()
{
    int i, ind=0;
    dfs(1, 1);
    for(i=1; i<=pn; i++)
    {
        reverse(path[i].begin(), path[i].end());
        for(auto j:path[i])
        {
            lin[++ind]=j;
            poz[j]=ind;
        }
    }
    build(1, 1, n);
}

void dfs(int nod, int lvl)
{
    int maxim=0;
    sz[nod]=1; niv[nod]=lvl;
    for(auto i:v[nod])
    {
        if(!sz[i])
        {
            p[i]=nod;
            dfs(i, lvl+1);
            if(sz[i]>maxim)
            {
                maxim=sz[i];
                nrp[nod]=nrp[i];
            }
            sz[nod]+=sz[i];
        }
    }
    if(nrp[nod]==0) nrp[nod]=++pn;
    path[nrp[nod]].push_back(nod);
}

void build(int nod, int st, int dr)
{
    if(st==dr)
    {
        aint[nod]=a[lin[st]];
        return;
    }
    int mij=(st+dr)/2;
    build(2*nod, st, mij);
    build(2*nod+1, mij+1, dr);
    aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}

void update(int nod, int st, int dr, int poz, int val)
{
    if(st==dr)
    {
        aint[nod]=val;
        return;
    }
    int mij=(st+dr)/2;
    if(poz<=mij) update(2*nod, st, mij, poz, val);
    else update(2*nod+1, mij+1, dr, poz, val);
    aint[nod]=max(aint[2*nod], aint[2*nod+1]);
}

int query(int nod, int st, int dr, int qst, int qdr)
{
    if(st>=qst && dr<=qdr) return aint[nod];
    int mij=(st+dr)/2, maxim=0;
    if(qst<=mij) maxim=max(maxim, query(2*nod, st, mij, qst, qdr));
    if(qdr>mij) maxim=max(maxim, query(2*nod+1, mij+1, dr, qst, qdr));
    return maxim;
}