Cod sursa(job #1689635)

Utilizator gabib97Gabriel Boroghina gabib97 Data 14 aprilie 2016 13:57:53
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.29 kb
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
using namespace std;
int n,m,p[100001],poz[100001],nrfii[100001],t,v[100001],T[100001],nr[100001],f[100001],niv[100001],pniv[100001];
int *aint[100001];
bool o[100001];
//p - in ce lant se afla fiecare nod
//poz - pe ce pozitie in lant
vector<int> G[100001],path[100001],Gp[100001];
void citire()
{
    int i,x,y;
    scanf("%i%i",&n,&m);
    for (i=1;i<=n;i++) scanf("%i",&v[i]);
    for (i=1;i<n;i++)
    {
        scanf("%i%i",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
}
void DFS(int s)
{
    int i,z=G[s].size(),m=0;
    nrfii[s]=1;
    for (i=0;i<z;i++)
        if (!nrfii[G[s][i]])
    {
        T[G[s][i]]=s;
        niv[G[s][i]]=niv[s]+1;
        DFS(G[s][i]);
        nrfii[s]+=nrfii[G[s][i]];
        if (nrfii[G[s][i]]>nrfii[m]) m=G[s][i];
    }

    if (z==1&&s!=1) //e frunza - creez un nou lant
    {
        path[++t].push_back(s);
        p[s]=t;
    }
    else
    {
        path[p[m]].push_back(s);
        p[s]=p[m];
        for (i=0;i<z;i++)
            if (p[s]!=p[G[s][i]])
            Gp[p[s]].push_back(p[G[s][i]]);
    }
}
void DFSp(int s)
{
    int z=Gp[s].size();
    o[s]=1;
    for (int i=0;i<z;i++)
        if (!o[Gp[s][i]])
    {
        pniv[Gp[s][i]]=pniv[s]+1;
        DFSp(Gp[s][i]);
    }
}
void buildAint(int k,int a,int b,int l)
{
    if (a==b)
    {
        aint[l][k]=v[path[l][a-1]];
        f[path[l][a-1]]=k;
        poz[path[l][a-1]]=a;
    }
    else
    {
        int m=(a+b)>>1,h=k<<1;
        buildAint(h,a,m,l);
        buildAint(h+1,m+1,b,l);

        aint[l][k]=max(aint[l][h],aint[l][h+1]);
    }
}
void splitTree()
{
    int i;
    DFS(1);
    for (i=1;i<=t;i++)
    {
        reverse(path[i].begin(),path[i].end()); //sortez lantul dupa nivel
        nr[i]=path[i].size();
        aint[i]=(int*) calloc(4*nr[i]+1,sizeof(int));
        buildAint(1,1,nr[i],i);
    }
}
void update(int i,int k)
{
    if (k)
    {
        int h=k<<1;
        aint[i][k]=max(aint[i][h],aint[i][h+1]);
        update(i,k>>1);
    }
}
int det(int k,int x,int y,int a,int b,int l)
{
    if (x>=a&&y<=b) return aint[l][k];
    else
    {
        int m=(x+y)>>1,r=0,h=k<<1;
        if (m>=a) r=max(r,det(h,x,m,a,b,l));
        if (m<b) r=max(r,det(h+1,m+1,y,a,b,l));
        return r;
    }
}
int query(int x,int y)
{
    int r=v[x];
    while (x!=y)
        if (p[x]==p[y])
        {
            if (niv[x]>niv[y]) swap(x,y);
            r=max(r,det(1,1,nr[p[x]],poz[x],poz[y],p[x]));
            y=x;
        }
        else
        {
            if (pniv[p[x]]>pniv[p[y]]) swap(x,y);
            r=max(r,det(1,1,nr[p[y]],1,poz[y],p[y]));
            y=T[path[p[y]][0]];
        }
    return r;
}
void solve()
{
    int q,x,y;
    while (m--)
    {
        scanf("%i%i%i",&q,&x,&y);

        if (q==0)
        {
            aint[p[x]][f[x]]=y;
            update(p[x],f[x]>>1);
        }
        else printf("%i\n",query(x,y));
    }
}
int main()
{
    freopen ("heavypath.in","r",stdin);
    freopen ("heavypath.out","w",stdout);
    citire();
    splitTree(); //descompun arborele in lanturi
    DFSp(p[1]);
    solve();
    fclose(stdin);
    fclose(stdout);
    return 0;
}