Cod sursa(job #809554)

Utilizator repp4raduRadu-Andrei Szasz repp4radu Data 8 noiembrie 2012 17:47:06
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.53 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define MAX 100005
#define pb push_back
#define leftSon (nod << 1)
#define rightSon ((nod << 1) + 1)

using namespace std;

vector<int> v[MAX], C[MAX];
int lvl[MAX], weight[MAX], l[MAX], lDad[MAX], lLvl[MAX], aInt[MAX << 2], val[MAX], lPoz[MAX];
int cnt, n, m, a, b, tip;

void dfs(int nod, int dad, int nivel)
{
    lvl[nod] = nivel;
    weight[nod] = 1;
    bool leaf = true; int heaviest = -1;
    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); it++)
    {
        if((*it) == dad) continue;
        leaf = false;
        dfs((*it), nod, nivel + 1);
        weight[nod] += weight[(*it)];
        if(!heaviest || weight[heaviest] < weight[(*it)]) heaviest = (*it);
    }
    if(leaf)
    {
        l[nod] = ++cnt;
        C[cnt].pb(nod);
        return;
    }
    l[nod] = l[heaviest];
    C[l[nod]].pb(nod);
    for(vector<int>::iterator it = v[nod].begin(); it != v[nod].end(); it++)
    {
        if((*it) == heaviest || (*it) == dad) continue;
        lDad[l[(*it)]] = nod;
        lLvl[l[(*it)]] = lvl[nod];
    }
}

void build(int nod, int left, int right, int decalaj, int lant)
{
    if(left == right)
    {
        aInt[nod + decalaj] = val[ C[lant][left - 1] ];
        return;
    }
    int m = (left + right) >> 1;
    build(leftSon, left, m, decalaj, lant);
    build(rightSon, m + 1, right, decalaj, lant);
    aInt[nod + decalaj] = max(aInt[leftSon + decalaj], aInt[rightSon + decalaj]);
}

void makePaths()
{
    dfs(1, 0, 1);
    for(int i = 1; i <= cnt; i++)
    {
        reverse(C[i].begin(), C[i].end());
        lPoz[i] = lPoz[i - 1] + C[i - 1].size() * 4;
        build(1, 1, C[i].size(), lPoz[i], i);
    }
}

void update(int nod, int left, int right, int poz, int val, int decalaj)
{
    if(left == right)
    {
        aInt[nod + decalaj] = val;
        return;
    }
    int m = (left + right) >> 1;
    if(poz <= m) update(leftSon, left, m, poz, val, decalaj);
    else update(rightSon, m + 1, right, poz, val, decalaj);
    aInt[nod + decalaj] = max(aInt[leftSon + decalaj], aInt[rightSon + decalaj]);
}

int query(int nod, int left, int right, int l, int r, int decalaj)
{
    if(l <= left && right <= r)
        return aInt[nod + decalaj];
    int m = (left + right) >> 1, sol = 0;
    if(l <= m) sol = max(sol, query(leftSon, left, m, l, r, decalaj));
    if(m < r) sol = max(sol, query(rightSon, m + 1, right, l, r, decalaj));
    return sol;
}

int main()
{
    ifstream in("heavypath.in");
    in>>n>>m;
    for(int i = 1; i <= n; i++) in>>val[i];
    for(int i = 1; i < n; i++)
    {
        in>>a>>b;
        v[a].pb(b);
        v[b].pb(a);
    }
    makePaths(); ofstream out("heavypath.out");
    for(int i = 1; i <= m; i++)
    {
        in>>tip>>a>>b;
        if(!tip) update(1, 1, C[l[a]].size(), lvl[a] - lLvl[l[a]], b, lPoz[l[a]]);
        else
        {
            int sol = 0;
            while(1)
            {
                if(l[a] == l[b])
                {
                    if(lvl[a] > lvl[b]) swap(a, b);
                    sol = max(sol, query(1, 1, C[l[a]].size(), lvl[a] - lLvl[l[a]], lvl[b] - lLvl[l[b]], lPoz[l[a]]));
                    break;
                }
                if(lLvl[l[a]] < lLvl[l[b]]) swap(a, b);
                sol = max(sol, query(1, 1, C[l[a]].size(), 1, lvl[a] - lLvl[l[a]], lPoz[l[a]]));
                a = lDad[l[a]];
            }
            out<<sol<<"\n";
        }
    }
    out.close();
    return 0;
}