Cod sursa(job #1167321)

Utilizator tester9x9Tester9x9 tester9x9 Data 4 aprilie 2014 19:42:01
Problema Heavy Path Decomposition Scor 80
Compilator cpp Status done
Runda Arhiva educationala Marime 4.04 kb
#include <fstream>
#include <algorithm>
#include <vector>
#define NM 100010
#define LM 17

using namespace std;

ifstream f("heavypath.in");
ofstream g("heavypath.out");

int N, M, K;
int V[NM];
int WPath[NM], WPos[NM], Level[NM];
int PathSize[NM], PathFather[NM];
int Delay[NM], Size[NM];
vector<int> G[NM];
int AI[8*NM];
int L, R, P, val;
int Ancestors[LM][NM];

void Update (int node, int delay, int S, int D)
{
    if (S>=D)
    {
        AI[node + delay]=val;
        return;
    }

    int M=(S+D)/2;

    if (P<=M)
        Update(2*node, delay, S, M);
    else
        Update(2*node+1, delay, M+1, D);

    AI[node + delay] = max( AI[2*node + delay], AI[2*node+1 + delay]);
}

void Query (int node, int delay, int S, int D)
{
    if (L<=S && D<=R)
    {
        val=max(val, AI[node + delay]);
        return;
    }

    int M=(S+D)/2;

    if (L<=M)
        Query(2*node, delay, S, M);
    if (R>M)
        Query(2*node+1, delay, M+1, D);
}

void Read ()
{
    f >> N >> M;
    for (int i=1; i<=N; i++)
        f >> V[i];

    for (int i=1; i<N; i++)
    {
        int a, b;
        f >> a >> b;
        G[a].push_back(b);
        G[b].push_back(a);
    }
}

void DF (int node, int father)
{
    int bigson=-1, bigsize=-1;
    Size[node]=1;
    Ancestors[0][node]=father;
    Level[node]=1+Level[father];

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

        DF(*it, node);
        Size[node]+=Size[*it];

        if (Size[*it]>bigsize)
        {
            bigsize=Size[*it];
            bigson=*it;
        }
    }

    if (bigson==-1)
    {
        ++K;
        WPath[node]=K;
        WPos[node]=1;
        PathSize[K]=1;

        return;
    }

    WPath[node]=WPath[bigson];
    PathSize[WPath[node]]++;
    WPos[node]=PathSize[WPath[node]];

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

        PathFather[WPath[*it]]=node;
    }
}

void BuildAncestors ()
{
    for (int j=1; (1 << j)<N; j++)
        for (int i=1; i<=N; i++)
            Ancestors[j][i]= Ancestors[j-1][ Ancestors[j-1][i] ];
}

void ComputeDelay ()
{
    for (int i=1; i<=K; i++)
        Delay[i]=Delay[i-1] + 4*PathSize[i-1] + 1;
}

void Build ()
{
    for (int i=1; i<=N; i++)
    {
        P=WPos[i];
        val=V[i];
        Update(1, Delay[WPath[i]], 1, PathSize[WPath[i]]);
    }
}

int GetLCA (int a, int b)
{
    int log1=0, log2=0;

    if (Level[a]>Level[b])
        swap(a, b);

    for (log1=0; (1 << log1)<Level[a]; log1++);
    for (log2=0; (1 << log2)<Level[b]; log2++);

    for (int k=log2; k>=0; k--)
        if (Ancestors[k][b]!=0 && (Level[b] - (1 << k)>=Level[a]))
            b=Ancestors[k][b];

    if (a==b)
        return a;

    for (int k=log1; k>=0; k--)
        if (Ancestors[k][a]!=0 && Ancestors[k][a]!=Ancestors[k][b])
        {
            a=Ancestors[k][a];
            b=Ancestors[k][b];
        }

    return Ancestors[0][a];
}

void GetANS (int x, int t)
{
    while (WPath[x]!=WPath[t])
    {
        L=WPos[x];
        R=PathSize[WPath[x]];
        Query(1, Delay[WPath[x]], 1, PathSize[WPath[x]]);

        x=PathFather[WPath[x]];
    }

    L=WPos[x];
    R=WPos[t];
    Query(1, Delay[WPath[x]], 1, PathSize[WPath[x]]);
}

void Solve ()
{
    for (int i=1; i<=M; i++)
    {
        int t, x, y;
        f >> t >> x >> y;

        if (t==0)
        {
            P=WPos[x];
            val=y;
            Update(1, Delay[WPath[x]], 1, PathSize[WPath[x]]);
        }
        if (t==1)
        {
            int z=GetLCA(x, y);

            val=0;
            GetANS(x, z);
            GetANS(y, z);

            g << val << '\n';
        }
    }
}

int main ()
{
    Read();
    DF(1, 0);
    BuildAncestors();
    ComputeDelay();
    Build();
    Solve();

    f.close();
    g.close();

    return 0;
}