Cod sursa(job #1971306)

Utilizator GinguIonutGinguIonut GinguIonut Data 20 aprilie 2017 10:47:01
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.78 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define nMax 100001
#define pb push_back
#define mkp make_pair
#define x first
#define y second

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

int n, m, nrLant;
int sons[nMax], viz[nMax], whatPath[nMax], tataLant[nMax], levTataLant[nMax], dimLant[nMax], pozLant[nMax], v[nMax], lev[nMax], arb[4*nMax];
vector<int> G[nMax], nodes[nMax];

void dfs(int node)
{
    sons[node]=1;
    viz[node]=1;
    int frunza=1, fiuLantMax=-1;

    for(vector<int>::iterator it=G[node].begin(); it!=G[node].end(); it++)
    {
        int fiu=*it;
        if(viz[fiu])
            continue;
        frunza=0;
        lev[fiu]=lev[node]+1;
        dfs(fiu);
        sons[node]+=sons[fiu];
        if(fiuLantMax==-1 || sons[fiu]>sons[fiuLantMax])
            fiuLantMax=fiu;

    }

    if(frunza)
    {
        whatPath[node]=++nrLant;
        nodes[nrLant].pb(node);
        dimLant[nrLant]++;
        return;
    }

    whatPath[node]=whatPath[fiuLantMax];
    nodes[whatPath[node]].pb(node);
    dimLant[whatPath[node]]++;

    for(vector<int>::iterator it=G[node].begin(); it!=G[node].end(); it++)
    {
        int fiu=*it;
        if(fiu==fiuLantMax || lev[fiu]<lev[node])
            continue;
        tataLant[whatPath[fiu]]=node;
        levTataLant[whatPath[fiu]]=lev[node];
    }
}

void build(int node, int st, int dr, int decalaj, int lant)
{
    if(st==dr)
    {
        arb[node+decalaj]=v[nodes[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 upDate(int node, int st, int dr, int poz, int decalaj, int val)
{
    if(st==dr)
    {
        arb[node+decalaj]=val;
        return;
    }

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

    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 Max=0;
    if(st>=pozst && dr<=pozdr)
        return arb[node+decalaj];

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

    return Max;
}

int main()
{
    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);
    }

    lev[1]=1;
    dfs(1);

    for(int i=1; i<=nrLant; i++)
    {
        reverse(nodes[i].begin(), nodes[i].end());
        if(i>1)
            pozLant[i]=pozLant[i-1]+dimLant[i-1]*4;
        build(1, 1, dimLant[i], pozLant[i], i);
    }

    for(int i=1; i<=m; i++)
    {
        fin>>op>>a>>b;
        if(op==0)
        {
            v[a]=b;
            upDate(1, 1, dimLant[whatPath[a]], lev[a]-levTataLant[whatPath[a]], pozLant[whatPath[a]], b);
            continue;
        }

        int Max=-1;
        while(whatPath[a]!=whatPath[b])
        {
            if(levTataLant[whatPath[a]]>levTataLant[whatPath[b]])
                swap(a, b);
            Max=max(Max, query(1, 1, dimLant[whatPath[b]], 1, lev[b]-levTataLant[whatPath[b]], pozLant[whatPath[b]]));
            b=tataLant[whatPath[b]];
        }
        if(lev[a]>lev[b])
            swap(a, b);
        Max=max(Max, query(1, 1, dimLant[whatPath[a]], lev[a]-levTataLant[whatPath[a]], lev[b]-levTataLant[whatPath[a]], pozLant[whatPath[a]]));
        fout<<Max<<'\n';
    }

}