Cod sursa(job #1964350)

Utilizator LucianTLucian Trepteanu LucianT Data 13 aprilie 2017 13:05:03
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.21 kb
#include <bits/stdc++.h>
#define maxN 100005
using namespace std;
int nrpaths;
int n,q,i,j,op,x,y,val[maxN];
int lvl[maxN],tata[maxN],weight[maxN];
int dim[maxN],pos[maxN],path[maxN];
vector<int> v[maxN],p[maxN],arb[maxN];

void build(int idx,int nod,int st,int dr)
{
    if(st==dr){
        arb[idx][nod]=val[p[idx][st-1]];
        return;
    }

    int mij=st+(dr-st)/2;
    build(idx,2*nod,st,mij);
    build(idx,2*nod+1,mij+1,dr);

    arb[idx][nod]=max(arb[idx][2*nod],arb[idx][2*nod+1]);
}
void update(int idx,int nod,int st,int dr,int poz,int value)
{
    if(st==dr){
        arb[idx][nod]=value;
        return;
    }

    int mij=st+(dr-st)/2;
    if(poz<=mij)
        update(idx,2*nod,st,mij,poz,value);
    else update(idx,2*nod+1,mij+1,dr,poz,value);

    arb[idx][nod]=max(arb[idx][2*nod],arb[idx][2*nod+1]);
}

int query(int idx,int nod,int st,int dr,int start,int stop)
{
    if(start<=st && dr<=stop)
        return arb[idx][nod];

    int mij=st+(dr-st)/2;
    int res1=-0x3f3f3f3f;
    int res2=-0x3f3f3f3f;

    if(start<=mij)
        res1=query(idx,2*nod,st,mij,start,stop);
    if(mij<stop)
        res2=query(idx,2*nod+1,mij+1,dr,start,stop);
    return max(res1,res2);
}

void dfs(int nod)
{
    bool leaf=true;
    int maxx=0;
    weight[nod]=1;
    for(auto it:v[nod])
        if(it!=tata[nod])
        {
            leaf=false;
            lvl[it]=lvl[nod]+1;
            tata[it]=nod;
            dfs(it);
            weight[nod]+=weight[it];
            if(weight[maxx]<weight[it])
                maxx=it;
        }

    if(leaf){
        nrpaths++;
        p[nrpaths].push_back(nod);
        path[nod]=nrpaths;
        dim[nrpaths]=1;
        return;
    }

    p[path[maxx]].push_back(nod);
    path[nod]=path[maxx];
    dim[path[nod]]++;
}


void build_paths()
{
    for(i=1;i<=nrpaths;i++)
    {
        reverse(p[i].begin(),p[i].end());
        arb[i].resize(4*dim[i]+1);
        for(j=0;j<dim[i];j++)
            pos[p[i][j]]=j+1;
        build(i,1,1,dim[i]);
    }
}

int solvequery(int a,int b)
{
    int l1,l2;

    int t1,t2,x,y;
    int res=0;
    x=a,y=b;
    t1=p[path[x]][0];
    t2=p[path[y]][0];

    while(path[x]!=path[y])
    {
        if(lvl[t1]<lvl[t2])
            swap(x,y),swap(t1,t2);
        int aux=query(path[x],1,1,dim[path[x]],1,pos[x]);
        res=max(res,aux);

        x=tata[t1];
        t1=p[path[x]][0];
        t2=p[path[y]][0];
    }
    int lim1=min(pos[x],pos[y]);
    int lim2=max(pos[x],pos[y]);
    int aux=query(path[x],1,1,dim[path[x]],lim1,lim2);
    res=max(res,aux);
    return res;
}

int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    scanf("%d %d",&n,&q);
    for(i=1;i<=n;i++)
        scanf("%d",&val[i]);
    for(i=1;i<n;i++){
        scanf("%d %d",&x,&y);
        v[x].push_back(y);
        v[y].push_back(x);
    }

    lvl[1]=1;
    dfs(1);
    build_paths();

    while(q--)
    {
        scanf("%d %d %d",&op,&x,&y);
        if(op==0){
            val[x]=y;
            update(path[x],1,1,dim[path[x]],pos[x],val[x]);
        }
        else printf("%d\n",solvequery(x,y));
    }
    return 0;
}