Cod sursa(job #2040903)

Utilizator ionanghelinaIonut Anghelina ionanghelina Data 16 octombrie 2017 17:35:09
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.64 kb
#include<bits/stdc++.h>
#define maxN 100005
using namespace std;
bool seen[maxN];
int pos[maxN];
int T[maxN],dp[maxN],niv[maxN];
int chaintop[maxN],where[maxN];
int A[4*maxN+5],fat[maxN],cnt;
vector<int> chain[maxN],v[maxN];
inline void dfs(int nod)
{
    seen[nod]=1;
    dp[nod]=1;
    int best=0;
    for(auto it:v[nod])
    {
        if(seen[it]) continue;
        niv[it]=1+niv[nod];
        dfs(it);
        fat[it]=nod;
        dp[nod]+=dp[it];
        if(dp[it]>dp[best]) best=it;
    }

    if(dp[nod]==1)
    {
        cnt++;
        chain[cnt].push_back(nod);
        chaintop[cnt]=nod;
        where[nod]=cnt;
    }
        else
    {
        int ch=where[best];

        chain[ch].push_back(nod);
        chaintop[ch]=nod;
        where[nod]=ch;
    }
}

inline void Update(int nod,int st,int dr,int val,int pos,int decalaj)
{
    if(st==dr)
    {
        A[nod+decalaj]=val;
        return;
    }
        else
    {
        int mid=(st+dr)>>1;
        if(pos<=mid) Update(2*nod,st,mid,val,pos,decalaj);
            else Update(2*nod+1,mid+1,dr,val,pos,decalaj);
        A[nod+decalaj]=max(A[2*nod+decalaj],A[2*nod+decalaj+1]);
    }
}
int sol;
inline void Query(int nod,int st,int dr,int a,int b,int decalaj)
{
    if(a<=st && dr<=b)
    {
        sol=max(sol,A[nod+decalaj]);
        return;
    }
        else
    {
        int mid=(st+dr)>>1;
        if(a<=mid) Query(2*nod,st,mid,a,b,decalaj);
        if(b>mid) Query(2*nod+1,mid+1,dr,a,b,decalaj);
    }
}
bool cmp(int a,int b)
{
    return niv[a]<niv[b];
}
int n,q,val[maxN],x,y,sp[maxN];
int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    scanf("%d%d",&n,&q);
    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].push_back(y);
        v[y].push_back(x);
    }
    niv[1]=1;
    dfs(1);
    for(int i=1;i<=cnt;i++)
    {
        sort(chain[i].begin(),chain[i].end(),cmp);
        chaintop[i]=chain[i][0];
    }
    for(int i=1;i<=cnt;i++)
        T[i]=fat[chaintop[i]];
    for(int i=1;i<=cnt;i++)
    {
        int sz=chain[i].size();
        for(int j=0;j<sz;j++)
            pos[chain[i][j]]=j;
    }
    //dec=0;
    for(int i=2;i<=cnt;i++)
    {
        sp[i]=sp[i-1]+4*chain[i-1].size();
    }
    int decal=0;
    for(int i=1;i<=cnt;i++)
    {
        int sz=chain[i].size();
        for(int j=0;j<sz;j++)
            Update(1,0,sz-1,val[chain[i][j]],j,decal);
        decal+=4*sz;
    }
    int op,ch,ch1,ch2;
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d%d",&op,&x,&y);
        if(!op)
        {
            val[x]=y;
            ch=where[x];
            int sz=chain[ch].size()-1;
            Update(1,0,sz,val[x],pos[x],sp[ch]);
        }
            else
        {
            sol=0;
            do
            {
            ch1=where[x];
            ch2=where[y];
            if(ch1==ch2)
            {
            //    if(pos[x]>pos[y]) swap(x,y);
                Query(1,0,chain[ch1].size()-1,min(pos[x],pos[y]),max(pos[x],pos[y]),sp[ch1]);
                break;
            }
                else
            {
                if(niv[T[ch1]]>niv[T[ch2]])
                {
                    Query(1,0,chain[ch1].size()-1,0,pos[x],sp[ch1]);
                    x=T[ch1];
                }
                    else
                {
                    Query(1,0,chain[ch2].size()-1,0,pos[y],sp[ch2]);
                    y=T[ch2];

                }
            }
            }while(1);
            printf("%d\n",sol);
        }
    }
    return 0;
}