Cod sursa(job #1653842)

Utilizator GinguIonutGinguIonut GinguIonut Data 16 martie 2016 17:17:32
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.87 kb
//heavy path decomposition(lungime lant) - n * log(n) * sqrt(n)

#include <fstream>
#include <vector>
#include <algorithm>

#define nMax 100001
#define pb push_back
#define mkp make_pair

using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, m, v[nMax], niv[nMax], l[nMax], lTata[nMax], lDim[nMax], lPoz[nMax], w[nMax], viz[nMax], nL, arb[4*nMax], lNiv[nMax];
pair<int, pair<int, int> > op[nMax];
vector<int> G[nMax], P[nMax];
void read()
{
    int x, y, t;
    fin>>n>>m;
    for(int i=1;i<=n;i++)
        fin>>v[i];
    for(int i=1;i<n;i++)
    {
        fin>>x>>y;
        G[x].pb(y);
        G[y].pb(x);
    }
    for(int i=1;i<=m;i++)
    {
        fin>>t>>x>>y;
        op[i]=mkp(t, mkp(x, y));
    }
}
void dfs(int node)
{
    viz[node]=1;
    int lN=-1, frunza=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);
        if(lN==-1)
            lN=fiu;
        else
            if(w[lN]<w[fiu])
                lN=fiu;
    }

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

    w[node]=w[lN]+1;
    l[node]=l[lN];
    ++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==lN || 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 poz, int val, int decalaj)
{
    if(st==dr)
    {
        arb[node+decalaj]=val;
        return;
    }

    int mid=st+(dr-st)/2;
    if(poz<=mid)
        upDate(2*node, st, mid, poz, val, decalaj);
    else
        upDate(2*node+1, mid+1, dr, poz, val, decalaj);
    arb[node+decalaj]=max(arb[2*node+decalaj], arb[2*node+1+decalaj]);
}
int query(int node, int st, int dr, int pozst, int pozdr, int decalaj)
{
    int rez=0;
    if(pozst<=st && pozdr>=dr)
        return arb[node+decalaj];

    int mid=st+(dr-st)/2;
    if(pozst<=mid)
        rez=max(rez, query(2*node, st, mid, pozst, pozdr, decalaj));
    if(pozdr>mid)
        rez=max(rez, query(2*node+1, mid+1, dr, pozst, pozdr, decalaj));
    return rez;
}
void solve()
{
    int t, x, y, sol;
    for(int i=1;i<=m;i++)
    {
        t=op[i].first, x=op[i].second.first, y=op[i].second.second;
        if(t==0)
            upDate(1, 1, lDim[l[x]], niv[x]-lNiv[l[x]], y, lPoz[l[x]]);
        else
        {
            sol=0;
            while(1)
            {
                if(l[x]==l[y])
                {
                    if(niv[x]>niv[y])
                        swap(x, y);
                    sol=max(sol, query(1, 1, lDim[l[x]], niv[x]-lNiv[l[x]], niv[y]-lNiv[l[x]], lPoz[l[x]]));
                    break;
                }
                if(lNiv[l[x]]<lNiv[l[y]])
                    swap(x, y);
                sol=max(sol, query(1, 1, lDim[l[x]], 1, niv[x]-lNiv[l[x]], lPoz[l[x]]));
                x=lTata[l[x]];
            }
            fout<<sol<<'\n';
        }
    }
}
int main()
{
    read();
    make_paths();
    solve();
    return 0;
}