Cod sursa(job #797970)

Utilizator paul_gabryelPaul Buda paul_gabryel Data 15 octombrie 2012 12:45:49
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.26 kb

#include <cstdio>
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

ifstream in ("heavypath.in");

#define pb push_back

const int N=100001;
int v[N],n,m,IN[N],out[N],len,F[N],T[N],Wh[N],LN,Pos,Whp[N],adi[N<<2],REZ;
vector<int> G[N],L[N];
bool H[N],isH[N];

void read ()
{

    in>>n>>m;
    for(int i=1;i<=n;++i)
        in>>v[i];
    for(int x,y,i=1;i<n;++i)
    {
        in>>x>>y;
        G[x].pb(y);
        G[y].pb(x);
    }
}

void DF (int nd)
{
    F[nd]=1;
    for(vector<int>::iterator it=G[nd].begin();it<G[nd].end();++it)
        if(*it!=T[nd])
        {
            IN[*it]=++len;
            T[*it]=nd;
            DF(*it);
            F[nd]+=F[*it];
            out[*it]=++len;
        }
}

void up (int nd,int ft,int bk,int vl)
{
    if(ft==bk)
    {
        adi[nd]=vl;
        return;
    }
    int mid=(ft+bk)>>1;
    if(Pos<=mid)
        up(nd<<1,ft,mid,vl);
    else
        up((nd<<1)+1,mid+1,bk,vl);
    adi[nd]=max(adi[nd<<1],adi[(nd<<1)+1]);
}

void DFS (int nd)
{
    for(vector<int>::iterator it=G[nd].begin();it<G[nd].end();++it)
        if(*it!=T[nd]&&F[*it]>=(F[nd]>>1))
        {
            H[*it]=1;
            isH[nd]=1;
            break;
        }
    for(vector<int>::iterator it=G[nd].begin();it<G[nd].end();++it)
        if(*it!=T[nd])
            DFS(*it);
    if(!isH[nd]&&Wh[nd]==0)
        for(++LN;;nd=T[nd])
        {
            ++Pos;
            up(1,1,n,v[nd]);
            L[LN].pb(nd);
            Wh[nd]=LN;
            Whp[nd]=Pos;
            if(!H[nd])
                break;
        }
}

bool is (int x,int y){
    return IN[x]<=IN[y]&&out[x]>=out[y];}

int LCA (int x,int y)
{
    if(is(x,y))
        return x;
    if(is(y,x))
        return y;
    for(;!is(L[Wh[x]].back(),y);x=T[L[Wh[x]].back()]);
    if(is(x,y))
        return x;
    int lg,lca;
    for(lg=1;(lg<<1)<L[Wh[x]].size();lg<<=1);
    for(lca=-1;lg;lg>>=1)
        if(lca+lg<L[Wh[x]].size()&&!is(L[Wh[x]][lca+lg],y))
            lca+=lg;
    ++lca;
    return L[Wh[x]][lca];
}

void query (int nd,int ft,int bk,int st,int dr)
{
    if(st<=ft&&bk<=dr)
    {
        REZ=max(REZ,adi[nd]);
        return;
    }
    int mid=(ft+bk)>>1;
    if(st<=mid)
        query(nd<<1,ft,mid,st,dr);
    if(mid<dr)
        query((nd<<1)+1,mid+1,bk,st,dr);
}

int get (int nw,int nd)
{
    int Sol=0;
    for(;LCA(L[Wh[nw]].back(),nd)==nd;nw=T[L[Wh[nw]].back()])
    {
        REZ=0;
        query(1,1,n,Whp[nw],Whp[L[Wh[nw]].back()]);
        Sol=max(Sol,REZ);
        if(L[Wh[nw]].back()==nd)
        {
            nw=nd;
            break;
        }
    }
    if(nw!=nd)
    {
        REZ=0;
        query(1,1,n,Whp[nw],Whp[nd]);
        Sol=max(Sol,REZ);
    }
    else
        Sol=max(Sol,v[nw]);
    return Sol;
}

int main ()
{
    read ();
    IN[1]=++len;
    DF (1);
    DFS (1);
    out[1]=++len;
    freopen ("heavypath.out","w",stdout);
    for(int t,x,y,i=1;i<=m;++i)
    {
        in>>t>>x>>y;
        if(t==0)
        {
            Pos=Whp[x];
            up(1,1,n,y);
            v[x]=y;
        }
        else
            printf("%d\n",max(get(x,LCA(x,y)),get(y,LCA(x,y))));
    }
    return 0;
}