Cod sursa(job #3234911)

Utilizator matei8787Matei Dobrea matei8787 Data 12 iunie 2024 17:56:44
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.56 kb
#include <bits/stdc++.h>

using namespace std;
ifstream f("heavypath.in");
ofstream out("heavypath.out");
const int N = 1e5+5;
const int LG = log(N);
int n, q;
vector <int> g[N];
int numere[N];
int a[LG][N], nrnodarb[N];
int lg[N];
void cit()
{
    for ( int i = 2 ; i <= N;  i++ )
    {
        lg[i] = 1 + lg[(i/2)];
    }
    f >> n >> q;
    for(int i = 1; i <= n; i++)
    {
        f >> numere[i];
    }
    for(int i = 1; i <= n - 1; i++)
    {
        int x, y;
        f >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

}
int h[N];
void dfs(int nod, int tata)
{
    int s = 0;
    h[nod] = h[tata] + 1;
    a[0][nod] = tata;
    for(int i : g[nod])
    {
        if(a[0][i] != 0 || i == tata)
            continue ;
        dfs(i, nod);
        s += nrnodarb[i];
    }
    nrnodarb[nod] = s + 1;
}
void prelca()
{
    for(int i = 1; (1 << i) <= n; i++)
    {
        for(int j = 1; j <= n; j++)
            a[i][j] = a[i - 1][a[i - 1][j]];
    }
}
int lca(int x, int y)
{
    int put = lg[h[x]];
 if(x == y)
    return x;
 if(h[x] == h[y])
 {
     while( a[put][x] == a[put][y] && put > 0)
     {
         put--;
     }
     return lca(a[put][x], a[put][y]);
 }
 put = lg[abs(h[y] - h[x])];
    if( h[x] > h[y])
    {
        return lca(a[put][x], y);
    }
    return lca(x, a[put][y]);
}
int fs(int nod)
{
    return 2*nod;
}
int fd(int nod)
{
    return 2*nod + 1;
}
struct aint{
    vector <int> arb;
    int nr_jos;
    void upd(int st, int dr, int nod, int poz, int val)
    {
        if(st == dr)
        {
            arb[nod] = val;
            return ;
        }
        int mij = (st + dr)/2;
        if(poz <= mij)
            upd(st, mij, fs(nod), poz, val);
        else upd(mij + 1, dr, fd(nod), poz, val);
        arb[nod] = max(arb[fs(nod)], arb[fd(nod)]);
    }
    int query(int st, int dr, int nod, int stx, int drx)
    {
        if( stx <= st && dr <= drx)
        {
            return arb[nod];
        }
        if( st > drx || stx > dr)
        {
            return INT_MIN;
        }
        int mij = (st + dr) /2;
        return max(query(st, mij, fs(nod), stx, drx), query(mij + 1, dr, fd(nod), stx, drx));
    }
    void build(int st, int dr, int nod, vector<int>& v)
    {
        if ( st == dr )
        {
            arb[nod] = v[st];
            return;
        }
        int mij = ( st + dr ) / 2;
        build(st, mij, fs(nod), v);
        build(mij+1, dr, fd(nod), v);
        arb[nod] = max(arb[fs(nod)], arb[fd(nod)]);
    }
    int query(int st, int dr)
    {
        return query(1, nr_jos, 1, st, dr);
    }
    aint(vector<int>& v)
    {
        vector<int> aux;
        aux.push_back(0);
        for ( int x : v )
        {
            aux.push_back(numere[x]);
        }
        arb.resize((aux.size() + 1)*4);
        nr_jos = aux.size() - 1;
        build(1, aux.size() - 1, 1, aux);
    }
    void afisare(int nod, int st, int dr)
    {
        cout<<"Sunt pe intervalul ["<<st<<", "<<dr<<"] cu numarul "<<arb[nod]<<'\n';
        if ( st == dr )
            return;
        int mij = ( st + dr ) / 2;
        afisare(fs(nod), st, mij);
        afisare(fd(nod), mij+1, dr);
    }
    void afisare()
    {
        afisare(1, 1, nr_jos);
    }
    void update(int poz, int val)
    {
        upd(1, nr_jos, 1, poz, val);
    }
    aint(){}
};
struct lant{
    aint tree;
    map <int, int> mp;
    lant (vector <int>& v)
    {
        tree = aint(v);
        for(int i = 0; i < v.size(); i++)
    {
        mp[v[i]] = i + 1;
    }
    }
    void afiseaza()
    {
        tree.afisare();
    }

};
vector <lant> lanturi;
map <int, int> mplant, lcap;

void hvy_light_comp(int nod, int tata,vector <int>& noduri_l)
{
    int fiugr = 0;
    for(int vec : g[nod])
    {
        if(vec == tata)
        continue ;
        if(nrnodarb[fiugr] < nrnodarb[vec])
            fiugr = vec;
    }
    noduri_l.push_back(nod);
    if(fiugr == 0)
    {
        lant l(noduri_l);
        lcap [lanturi.size()] = noduri_l[0];
        for(int x : noduri_l)
            mplant[x] = lanturi.size();
        lanturi.push_back(l);
        return ;
    }
    hvy_light_comp(fiugr, nod, noduri_l);
    for(int vec : g[nod])
    {
        if(vec == tata || vec == fiugr)
            continue ;
        vector <int> aux;
        hvy_light_comp(vec, nod, aux);
    }
}
void update(int nod, int val)
{
    lanturi[mplant[nod]].tree.update(lanturi[mplant[nod]].mp[nod], val);
}
int queryup(int from, int to)
{
    int ans = INT_MIN;
    while ( mplant[from] != mplant[to] )
    {
        ans = max(ans, lanturi[mplant[from]].tree.query(lanturi[mplant[from]].mp[lcap[mplant[from]]], lanturi[mplant[from]].mp[from]));
        from = a[0][lcap[mplant[from]]];
    }
    ans = max(ans, lanturi[mplant[from]].tree.query(
            min(lanturi[mplant[from]].mp[from], lanturi[mplant[from]].mp[to]),
            max(lanturi[mplant[from]].mp[from], lanturi[mplant[from]].mp[to])
            ));
    return ans;
}
int query(int x, int y)
{
    int aux = lca(x, y);
    return max(queryup(x, aux),queryup(y, aux));
}
void rez()
{
    dfs(1, 0);
    prelca();
    vector<int> aux;
    hvy_light_comp(1, 0, aux);
    for ( int i = 1 ; i <= q ; i++ )
    {
        int op, x, y;
        f>>op>>x>>y;
        if ( op == 0 )
        {
            update(x, y);
        }
        else
        {
            out<<query(x, y)<<'\n';
        }
    }
}
int main()
{
    cit();
    rez();
    return 0;
}