Cod sursa(job #1632193)

Utilizator AdrianaMAdriana Moisil AdrianaM Data 5 martie 2016 22:35:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.91 kb
#include <fstream>
#include <iostream>
#include <vector>
#define INF 0x3f3f3f3f
using namespace std;

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

using VI = vector<int>;
using VVI = vector<VI>;

class AIB{
public:
    AIB(const VI &v)
    {
        n = v.size();
        for ( N = 1; N < n; N <<= 1 );
        arb = VI(2 * N);
        for ( int i = 0; i < n; ++i )
            arb[i + N] = v[i];
        for ( int i = N - 1; i; --i )
            arb[i] = max(arb[2 * i], arb[2 * i + 1]);
    }
    void update(int poz, int val)
    {
        arb[poz += N] = val;
        for ( poz >>= 1; poz; poz >>= 1 )
            arb[poz] = max(arb[2 * poz], arb[2 * poz + 1]);
    }
    int query(int st, int dr)
    {
        st += N;
        dr += N;
        int answ = 0;
        while ( st <= dr )
        {
            answ = max(answ, max(arb[st], arb[dr]));
            st = ( st + 1 ) >> 1;
            dr = ( dr - 1 ) >> 1;
        }
        return answ;
    }
private:
    int n, N;
    VI arb;
};

int n, m;
VI v, grup, poz, t, h, nr;
VVI g, paths;
vector<AIB> a;

void Read();
void Build();
void DF(int nod);
int Query(int x, int y);

int main()
{
    Read();
    Build();
    int tip, x, y;
    while ( m-- )
    {
        is >> tip >> x >> y;
        if ( !tip )
            a[grup[x]].update(poz[x], y);
        else
            os << Query(x, y) << "\n";
    }
    is.close();
    os.close();
    return 0;
}

int Query(int x, int y)
{
    if ( grup[x] == grup[y] )
    {
        if ( poz[x] > poz[y] )
            swap(x, y);
        return a[grup[x]].query(poz[x], poz[y]);
    }
    if ( h[paths[grup[x]].back()] < h[paths[grup[y]].back()] )
        swap(x, y);
    return max(a[grup[x]].query(poz[x], paths[grup[x]].size() - 1), Query(t[paths[grup[x]].back()], y));
}

void Build()
{
    grup = poz = t = h = nr = VI(n + 1);
    DF(1);
    VI aux;
    for ( const auto &i : paths )
    {
        aux.clear();
        for ( const auto &j : i )
            aux.push_back(v[j]);
        a.push_back(aux);
    }
}

void DF(int nod)
{
    int hs = 0;
    nr[nod] = 1;
    for ( const auto &nodv : g[nod] )
        if ( !nr[nodv] )
        {
            t[nodv] = nod;
            h[nodv] = h[nod] + 1;
            DF(nodv);
            nr[nod] += nr[nodv];
            if ( nr[nodv] > nr[hs] )
                hs = nodv;
        }
    if ( !hs )
    {
        grup[nod] = paths.size();
        paths.push_back(VI(1, nod));
        return;
    }
    grup[nod] = grup[hs];
    poz[nod] = paths[grup[nod]].size();
    paths[grup[nod]].push_back(nod);
}

void Read()
{
    is >> n >> m;
    v = VI(n + 1);
    for ( int i = 1; i <= n; ++i )
        is >> v[i];
    int x, y;
    g = VVI(n + 1);
    for ( int i = 1; i < n; ++i )
    {
        is >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
}