Cod sursa(job #980547)

Utilizator andrettiAndretti Naiden andretti Data 4 august 2013 22:25:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.71 kb
#include<stdio.h>
#include<algorithm>
#include<vector>
#define pb push_back
#define maxn 100005
#define maxait 1<<20
using namespace std;

int n,m,nrp,nrl,sol;
int ait[maxait];
int v[maxn],lev[maxn],nr[maxn],liniar[maxn];
int pfather[maxn],path[maxn],lpos[maxn],start[maxn];
vector <int> l[maxn],p[maxn];

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

void dfs(int k,int level,int father)
{
    int nrc=0,ind;
    lev[k]=level; nr[k]=1;
    for(unsigned int i=0;i<l[k].size();i++)
     if(!lev[l[k][i]])
     {
         dfs(l[k][i],level+1,k);
         nr[k]+=nr[l[k][i]];
         if(nr[l[k][i]]>nrc) nrc=nr[l[k][i]],ind=l[k][i];
     }

    if(l[k].size()==1 && k!=1) p[++nrp].pb(k),path[k]=nrp,pfather[nrp]=father;
    else p[path[ind]].pb(k),path[k]=path[ind],pfather[path[ind]]=father;
}

void build(int k,int left,int right)
{
    if(left==right) {ait[k]=v[liniar[left]]; return;}
    int mid=(left+right)>>1;
    build(2*k,left,mid);
    build(2*k+1,mid+1,right);
    ait[k]=max(ait[2*k],ait[2*k+1]);
}

void make_paths()
{
    for(int k=1;k<=nrp;k++)
    {
        start[k]=nrl+1;
        reverse(p[k].begin(),p[k].end());
        for(unsigned int i=0;i<p[k].size();i++)
          liniar[++nrl]=p[k][i],lpos[p[k][i]]=nrl;
    }
    build(1,1,n);
}

void update(int k,int left,int right,int posc)
{
    if(left==right) {ait[k]=v[liniar[left]]; return;}
    int mid=(left+right)>>1;
    if(posc<=mid) update(2*k,left,mid,posc);
    else update(2*k+1,mid+1,right,posc);

    ait[k]=max(ait[2*k],ait[2*k+1]);
}

void query(int k,int left,int right,int x,int y)
{
    if( x<=left && right<=y ) {sol=max(sol,ait[k]); return;}
    int mid=(left+right)>>1;
    if(x<=mid) query(2*k,left,mid,x,y);
    if(y>mid) query(2*k+1,mid+1,right,x,y);
}

void solve()
{
    int type,x,y;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&type,&x,&y);
        if(!type)
        {
            v[x]=y;
            update(1,1,n,lpos[x]);
            continue;
        }
        sol=0;
        while(path[x]!=path[y])
        {
            if(lev[pfather[path[x]]]<lev[pfather[path[y]]]) swap(x,y);
            query(1,1,n,start[path[x]],lpos[x]);
            x=pfather[path[x]];
        }
        if(lpos[x]>lpos[y]) swap(x,y);
        query(1,1,n,lpos[x],lpos[y]);
        printf("%d\n",sol);
    }
}

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

    read();
    dfs(1,1,0);
    make_paths();
    solve();

    fclose(stdin);
    fclose(stdout);
    return 0;
}