Cod sursa(job #1975857)

Utilizator DenisONIcBanu Denis Andrei DenisONIc Data 2 mai 2017 11:50:41
Problema Heavy Path Decomposition Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.48 kb
#include <fstream>
#include <vector>
#include <cmath>
#define Nmax 100001
#define pb push_back
using namespace std;

ofstream g("heavypath.out");


struct nod{
    nod *st,*dr;
    int val;
    nod (nod *_st,nod *_dr,int _val) : st(_st), dr(_dr), val(_val) {};
}*AINT[Nmax];
bool uz[Nmax];

vector<int> V[Nmax],L[Nmax];
int val[Nmax],x,y,Lid[Nmax],poz[Nmax],nrL,n,m,niv[Nmax],T[Nmax],t;

int lg(int x)
{
    int rez = 1<<((int)log2(L[x].size()));
    if (rez<L[x].size())
        rez*=2;
    return rez;
}

void update(nod *N,int st,int dr,int poz,int val)
{

    if (st==dr)
    {
        N->val = val;
        return;
    }

    int mid = (st+dr)/2;

    if (poz>mid)
    {
        if (N->dr == NULL)
            N->dr = new nod(NULL,NULL,0);
        update(N->dr,mid+1,dr,poz,val);
    }
    else
    {
        if (N->st == NULL)
            N->st = new nod(NULL,NULL,0);
        update(N->st,st,mid,poz,val);
    }
    int a = 0,b = 0;
    if (N->st!=NULL)
        a = N->st->val;
    if (N->dr!=NULL)
        b = N->dr->val;

    N->val = max(a,b);
}

void make_aint(vector<int> &L,int x)
{
    AINT[x] = new nod(NULL,NULL,0);
    for (int i=0;i<L.size();i++)
        update(AINT[x],0,lg(x),i+1,val[L[i]]);
}

int dfs(int nod,int p,int nv)
{
    int nr = 0,x,mx = -1,sav = -1;
    niv[nod] = nv;
    uz[nod] = 1;
    for (int i=0;i<V[nod].size();i++)
    {
        if (!uz[V[nod][i]])
        {
            x = dfs(V[nod][i],nod,nv+1);
            if (x>mx)
            {
                mx = x;
                sav = V[nod][i];
            }
            nr+=x;
        }
    }
    if (sav==-1)
    {
        Lid[nod] = ++nrL;
        poz[nod] = L[Lid[nod]].size()+1;
        L[Lid[nod]].pb(nod);
    }
    else
    {
        Lid[nod] = Lid[sav];
        poz[nod] = L[Lid[nod]].size()+1;
        L[Lid[nod]].pb(nod);
    }

    for (int i=0;i<V[nod].size();i++)
        if (V[nod][i]!=p)
            T[Lid[V[nod][i]]] = nod;

    return nr+1;
}

int query(nod *N,int st,int dr,int L,int R)
{
    if (L<=st && dr<=R)
        return N->val;

    int mid = (st+dr)/2,a=0,b=0;
    if (L<=mid)
    {
        if (N->st == NULL)
            N->st = new nod(NULL,NULL,0);
        a = query(N->st,st,mid,L,R);
    }
    if (R>mid)
    {
        if (N->dr == NULL)
            N->dr = new nod(NULL,NULL,0);
        b = query(N->dr,mid+1,dr,L,R);
    }

    return max(a,b);
}

int path(int x,int y)
{
    if (poz[x]>poz[y])
        swap(x,y);
    if (Lid[x]==Lid[y])
        return query(AINT[Lid[x]],0,lg(Lid[x]),poz[x],poz[y]);
    else if (T[Lid[x]] == T[Lid[y]])
        return max(query(AINT[Lid[x]],0,lg(Lid[x]),poz[x],lg(Lid[x])),query(AINT[Lid[y]],0,lg(Lid[y]),poz[y],lg(Lid[y])));
    if (niv[T[Lid[x]]]<niv[T[Lid[y]]])
        swap(x,y);
    return max(query(AINT[Lid[x]],0,lg(Lid[x]),poz[x],lg(Lid[x])),path(T[Lid[x]],y));
}

int main()
{
    freopen("heavypath.in","r",stdin);

    scanf("%d%d",&n,&m);


    for (int i=1;i<=n;i++)
        scanf("%d",&val[i]);

    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);
        V[x].pb(y);
        V[y].pb(x);
    }

    dfs(1,-1,1);

    for (int i=1;i<=nrL;i++)
        make_aint(L[i],i);

    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&t,&x,&y);
        if (t==0)
            update(AINT[Lid[x]],0,lg(Lid[x]),poz[x],y);
        if (t==1)
        {
            g<<path(x,y)<<'\n';
        }
    }

    return 0;
}