Cod sursa(job #1891596)

Utilizator GinguIonutGinguIonut GinguIonut Data 24 februarie 2017 10:27:32
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.87 kb
#include <fstream>
#include <vector>
#include <algorithm>

#define nMax 100001
#define pb push_back

using namespace std;

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

int n, nrQuery, nrLanturi;
int arb[4*nMax], whatPath[nMax], sons[nMax], viz[nMax], pozLant[nMax], dimLant[nMax], v[nMax], lev[nMax], tataLant[nMax], levTataLant[nMax];
vector<int> noduriLant[nMax], G[nMax];

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

void dfs(int node)
{
    viz[node]=1;
    sons[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)
            fiuLantMax=fiu;
        else
            if(sons[fiuLantMax]<sons[fiu])
                fiuLantMax=fiu;
    }

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

    whatPath[node]=whatPath[fiuLantMax];
    dimLant[whatPath[node]]++;
    noduriLant[whatPath[node]].pb(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];
    }
}

int query(int node, int st, int dr, int pozst, int pozdr, int decalaj)
{
    int Sol=0;
    if(st>=pozst && dr<=pozdr)
        return arb[node+decalaj];

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

int main()
{
    int a, b;
    fin>>n>>nrQuery;
    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<=nrLanturi; i++)
    {
        reverse(noduriLant[i].begin(), noduriLant[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<=nrQuery; i++)
    {
        int op, x, y;
        fin>>op>>x>>y;
        if(op==0)
            upDate(1, 1, dimLant[whatPath[x]], pozLant[whatPath[x]], lev[x]-levTataLant[whatPath[x]], y);
        else
        {
            int Sol=0;
            while(whatPath[x]!=whatPath[y])
            {
                if(levTataLant[whatPath[x]]>levTataLant[whatPath[y]])
                    swap(x, y);
                Sol=max(Sol, query(1, 1, dimLant[whatPath[y]], 1, lev[y]-levTataLant[whatPath[y]], pozLant[whatPath[y]]));
                y=tataLant[whatPath[y]];
            }
            if(lev[x]>lev[y])
                swap(x, y);
            Sol=max(Sol, query(1, 1, dimLant[whatPath[x]], lev[x]-levTataLant[whatPath[x]], lev[y]-levTataLant[whatPath[x]], pozLant[whatPath[y]]));
            fout<<Sol<<'\n';
        }
    }
}