Cod sursa(job #2474820)

Utilizator PetrescuAlexandru Petrescu Petrescu Data 15 octombrie 2019 20:53:14
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.04 kb
#include <fstream>
#include <iostream>
#include <vector>
#define MAX 100001
#define LOG 22

using namespace std;

int lastId;
int value[MAX], depth[MAX];
int subarb[MAX], head[MAX], heavyId[MAX], P[MAX], aint[3 * MAX];
vector<int>graph[MAX];

void DFS(int nod, int parent, int lv)
{

    P[nod] = parent;
    depth[nod] = lv;
    subarb[nod] = 1;

    for(auto child : graph[nod])
    {
        if(child != parent)
        {
            DFS(child, nod, lv + 1);

            subarb[nod] += subarb[child];
        }
    }
}

void heavyDecomposition(int nod, int headCh)
{
    lastId++;

    head[nod] = headCh;
    heavyId[nod] = lastId;

    int heavyChild = -1;

    for(auto child : graph[nod])
    {
        if(child != P[nod])
        {
            if(heavyChild == -1)heavyChild = child;
            else if(subarb[child] > subarb[heavyChild])heavyChild = child;
        }
    }

    if(heavyChild != -1)heavyDecomposition(heavyChild, headCh);

    for(auto child : graph[nod])
    {
        if(child != P[nod] && child != heavyChild)
            heavyDecomposition(child, child);
    }
}

void bitSwap(int &a, int &b)
{
    a ^= b;
    b ^= a;
    a ^= b;
}

void updateAint(int nod, int st, int dr, int leaf, int value)
{
    if(st == dr)
    {
        aint[nod] = value;

        return;
    }

    int mij = (st + dr) >> 1;

    if(leaf <= mij)updateAint(nod * 2, st, mij, leaf, value);
    else updateAint(nod * 2 + 1, mij + 1, dr, leaf, value);

    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}

int queryAint(int nod, int st, int dr, int a, int b)
{
    if(a <= st && dr <= b)return aint[nod];

    int mij = (st + dr) >> 1;

    int leftSol, rightSol;

    leftSol = rightSol = -1;

    if(mij >= a)leftSol = queryAint(nod * 2, st, mij, a, b);
    if(mij < b)rightSol = queryAint(nod * 2 + 1, mij + 1, dr, a, b);

    return max(leftSol, rightSol);
}

int heavyQuery(int a, int b, int n)
{
    if(head[a] == head[b])
    {

        if(heavyId[a] > heavyId[b])bitSwap(a, b);

        return queryAint(1, 1, n, heavyId[a], heavyId[b]);
    }
    else
    {
        if(depth[head[a]] < depth[head[b]])bitSwap(a, b);

        return max(queryAint(1, 1, n, heavyId[head[a]], heavyId[a]), heavyQuery(P[head[a]], b, n));
    }
}

int main()
{
    int n, m, i, t, a, b;

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

    fin >> n >> m;

    for(i = 1; i <= n; i++)fin >> value[i];

    for(i = 1; i <= n - 1; i++)
    {
        fin >> a >> b;

        graph[a].push_back(b);
        graph[b].push_back(a);
    }

    DFS(1, 0, 1);
    heavyDecomposition(1, 1);

    for(i = 1; i <= n; i++)updateAint(1, 1, n, heavyId[i], value[i]);

    for(i = 1; i <= m; i++)
    {
        fin >> t >> a >> b;

        if(t == 0)
        {
            value[a] = b;
            updateAint(1, 1, n, heavyId[a], b);
        }
        else fout << heavyQuery(a, b, n) << '\n';
    }

    fin.close();
    fout.close();

    return 0;
}