Cod sursa(job #2920853)

Utilizator VladPislaruPislaru Vlad Rares VladPislaru Data 26 august 2022 13:44:12
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.24 kb

#include <bits/stdc++.h>

using namespace std;

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

const int MaxN = 1e5 + 5;
int n, q, niv[MaxN], what_lant[MaxN];
vector< vector <int> > adj;
vector <int> val;
int sz[MaxN];
int nr_lant;
int poz_lant[MaxN];

struct
{
    int father;
    vector <int> path;//retin lantul
}lant[MaxN];

void Citire()
{
    fin >> n >> q;

    val.resize(MaxN);
    int i;
    for(i = 1; i <= n; ++i)
        fin >> val[i];

    adj.resize(MaxN);

    for(i = 1; i < n; ++i)
    {
        int a, b;
        fin >> a >> b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
}

vector< pair <int, int> > maxSon; // sz-ul maxim al unui fiu al nodului i si nodul asociat maximului

//determin sz-ul
int DFS(int node, int d)
{
    niv[node] = d;
    sz[node] = 1;

    for(int i : adj[node])
    {
        if(sz[i] == 0)// daca nu e vizitat
        {
            sz[node] += DFS(i, d + 1);
            if(maxSon[node].first < sz[i])
                maxSon[node].first = sz[i], maxSon[node].second = i;
        }
    }

    return sz[node];
}


void Make_lant(int node, int nr)
{
    what_lant[node] = nr;

    //indexare de la 1
    if(lant[nr].path.empty())
        lant[nr].path.push_back(0);

    lant[nr].path.push_back(node);
    poz_lant[node] = lant[nr].path.size() - 1;
    for(int i : adj[node])
    {
        if(niv[i] < niv[node])
            continue;

        if(i == maxSon[node].second) // daca am gasit maximul
            Make_lant(i, nr);
        else
        {
            ++nr_lant;
            lant[nr_lant].father = node;
            Make_lant(i, nr_lant);
        }
    }
}

vector < vector <int> > aint; // aint[i] - arborele de intervale asociat lantului i

void Build(int nr, int node, int st, int dr)
{
    if(st == dr)
        aint[nr][node] = val[lant[nr].path[st]];
    else
    {
        int mij = (st + dr) / 2;
        Build(nr, 2 * node, st, mij);
        Build(nr, 2 * node + 1, mij + 1, dr);
        aint[nr][node] = max(aint[nr][2 * node], aint[nr][2 * node + 1]);
    }
}

void Init()
{
    int i;
    aint.resize(nr_lant + 2);
    for(i = 1; i <= nr_lant; ++i)
    {
        aint[i].resize(1ll << int(log2(lant[i].path.size()) + 2));
        Build(i, 1, 1, lant[i].path.size() - 1);
    }
}

void Update(int nr, int node, int st, int dr, int poz, int val)
{
    if(st == dr && st == poz)
        aint[nr][node] = val;
    else
    {
        int mij = (st + dr) / 2;
        if(poz <= mij)
            Update(nr, 2 * node, st, mij, poz, val);
        else Update(nr, 2 * node + 1, mij + 1, dr, poz, val);
        aint[nr][node] = max(aint[nr][2 * node], aint[nr][2 * node + 1]);
    }
}

int Query(int nr, int node, int st, int dr, int x, int y)
{
    if(x <= st && dr <= y)
        return aint[nr][node];
    else
    {
        int mij = (st + dr) / 2, val1, val2;
        val1 = val2 = INT_MIN;

        if(x <=  mij)
            val1 = Query(nr, 2 * node, st, mij, x, y);

        if(y > mij)
            val2 = Query(nr, 2 * node + 1, mij + 1, dr, x, y);
        return max(val1, val2);
    }
}

int Solve(int x, int y)
{
    if(what_lant[x] == what_lant[y])
    {
        int aux = Query(what_lant[x], 1, 1, lant[what_lant[x]].path.size() - 1, min(poz_lant[x], poz_lant[y]), max(poz_lant[x], poz_lant[y]));
        return aux;
    }
    if(niv[lant[what_lant[x]].father] < niv[lant[what_lant[y]].father])
        swap(x, y);
    int val1 = Query(what_lant[x], 1, 1, lant[what_lant[x]].path.size() - 1, 1, poz_lant[x]);
    int val2 = Solve(lant[what_lant[x]].father, y);

    return max(val1, val2);
}

int main()
{
    Citire();
    maxSon.resize(MaxN);
    DFS(1, 1);
    maxSon.clear();
    ++nr_lant;
    lant[1].father = 0;
    Make_lant(1, 1);
    adj.clear();
    Init();
    int query_type, x, y;
    for(int i = 1; i <= q; ++i)
    {
        fin >> query_type >> x >> y;

        if(query_type == 0)//update in aint, indicele x devine y
        {
            Update(what_lant[x], 1, 1, lant[what_lant[x]].path.size() - 1, poz_lant[x], y);
        }
        else
        {
            fout << Solve(x, y) << '\n';
        }
    }
    return 0;
}