Cod sursa(job #1677806)

Utilizator GinguIonutGinguIonut GinguIonut Data 6 aprilie 2016 20:02:21
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.05 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define pb push_back
#define mkp make_pair
#define piii pair<int, pair<int, int> >
#define nMax 100005
#define qMax 100005
using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, m, Sol, nL;
int v[nMax], niv[nMax], lNiv[nMax], lTata[nMax], w[nMax], viz[nMax], l[nMax], arb[4*nMax], lDim[nMax], lPoz[nMax];
piii q[qMax];
vector<int> G[nMax], P[nMax];
void read()
{
    int op, a, b;
    fin>>n>>m;

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

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

    for(int i=1;i<=m;i++)
    {
        fin>>op>>a>>b;
        q[i]=mkp(op, mkp(a, b));
    }
}
void dfs(int node)
{
    viz[node]=1;
    w[node]=1;
    int frunza=1, hN=-1;

    for(vector<int>::iterator it=G[node].begin();it!=G[node].end();it++)
    {
        int fiu=*it;
        if(viz[fiu])
            continue;

        frunza=0;
        niv[fiu]=niv[node]+1;
        dfs(fiu);

        w[node]+=w[fiu];

        if(hN==-1)
            hN=fiu;
        else
            if(w[fiu]>w[hN])
                hN=fiu;
    }

    if(frunza)
    {
        l[node]=++nL;
        lDim[nL]++;
        P[nL].pb(node);
        return;
    }

    l[node]=l[hN];
    lDim[l[node]]++;
    P[l[node]].pb(node);

    for(vector<int>::iterator it=G[node].begin();it!=G[node].end();it++)
    {
        int fiu=*it;
        if(fiu==hN || niv[fiu]<niv[node])
            continue;

        lTata[l[fiu]]=node;
        lNiv[l[fiu]]=niv[node];
    }
}
void build(int node, int st, int dr, int decalaj, int lant)
{
    if(st==dr)
    {
        arb[node+decalaj]=v[P[lant][st-1]];
        return;
    }

    int mid=st+(dr-st)/2;
    build(2*node, st, mid, decalaj, lant);
    build(2*node+1, mid+1, dr, decalaj, lant);

    arb[node+decalaj]=max(arb[2*node+decalaj], arb[2*node+1+decalaj]);
}
void make_paths()
{
    niv[1]=1;
    dfs(1);

    for(int i=1;i<=nL;i++)
    {
        reverse(P[i].begin(), P[i].end());
        if(i>1)
            lPoz[i]=lPoz[i-1]+lDim[i-1]*4;
        build(1, 1, lDim[i], lPoz[i], i);
    }
}
void upDate(int node, int st, int dr, int decalaj, int poz, int val)
{
    if(st==dr)
    {
        arb[node+decalaj]=val;
        return;
    }

    int mid=st+(dr-st)/2;
    if(poz<=mid)
        upDate(2*node, st, mid, decalaj, poz, val);
    else
        upDate(2*node+1, mid+1, dr, decalaj, poz, val);

    arb[node+decalaj]=max(arb[2*node+decalaj], arb[2*node+1+decalaj]);
}
int query(int node, int st, int dr, int decalaj, int pozst, int pozdr)
{
    int Max=0;
    if(pozst<=st && pozdr>=dr)
        return arb[node+decalaj];

    int mid=st+(dr-st)/2;
    if(pozst<=mid)
        Max=max(Max, query(2*node, st, mid, decalaj, pozst, pozdr));
    if(pozdr>mid)
        Max=max(Max, query(2*node+1, mid+1, dr, decalaj, pozst, pozdr));

    return Max;
}
void write()
{
    fout<<Sol<<'\n';
}
void solve()
{
    int op, a, b;

    for(int i=1;i<=m;i++)
    {
        op=q[i].first, a=q[i].second.first, b=q[i].second.second;

        if(op==0)
        {
            upDate(1, 1, lDim[l[a]], lPoz[l[a]], niv[a]-lNiv[l[a]], b);
            continue;
        }
        if(op==1)
        {
            Sol=0;
            while(1)
            {
                if(l[a]==l[b])
                {
                    if(niv[a]>niv[b])
                        swap(a, b);

                    Sol=max(Sol, query(1, 1, lDim[l[a]], lPoz[l[a]], niv[a]-lNiv[l[a]], niv[b]-lNiv[l[a]]));
                    write();
                    break;
                }
                else
                {
                    if(lNiv[l[a]]>lNiv[l[b]])
                        swap(a, b);

                    Sol=max(Sol, query(1, 1, lDim[l[b]], lPoz[l[b]], 1, niv[b]-lNiv[l[b]]));
                    b=lTata[l[b]];
                }
            }
        }
    }
}
int main()
{
    read();
    make_paths();
    solve();
    return 0;
}