Cod sursa(job #2412148)

Utilizator ionanghelinaIonut Anghelina ionanghelina Data 21 aprilie 2019 18:25:23
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda qsasdasgegs Marime 3.81 kb
#include<bits/stdc++.h>
using namespace std;

const int maxN=(1e5)+5;
int A[4*maxN+5];
int val[maxN];
vector<int> v[maxN],ch[maxN];

void build(int nod,int st,int dr,int offset,int i)
{
    if(st==dr)
    {
        A[offset+nod]=val[ch[i][st-1]];
        return;
    }

    int mid=(st+dr)>>1;

    build(2*nod,st,mid,offset,i);
    build(2*nod+1,mid+1,dr,offset,i);

    A[offset+nod]=max(A[offset+2*nod],A[offset+2*nod+1]);
}

int where[maxN],pos[maxN];

void update(int nod,int st,int dr,int pos,int offset,int i)
{
    if(st==dr)
    {
        A[offset+nod]=val[ch[i][st-1]];
        return;
    }

    int mid=(st+dr)>>1;

    if(pos<=mid) update(2*nod,st,mid,pos,offset,i);
        else update(2*nod+1,mid+1,dr,pos,offset,i);

    A[offset+nod]=max(A[offset+2*nod],A[offset+2*nod+1]);

}
int chains,w[maxN],t[maxN],T[maxN],lvl[maxN];
int sz[maxN];
bool cmp(int x,int y)
{
    return lvl[x]<lvl[y];
}

inline int query(int nod,int st,int dr,int a,int b,int offset)
{
    if(a<=st && dr<=b)
    {
        return A[offset+nod];
    }

    int mid=(st+dr)>>1;

    int q=0;

    if(a<=mid) q=max(q,query(2*nod,st,mid,a,b,offset));
    if(b>mid) q=max(q,query(2*nod+1,mid+1,dr,a,b,offset));
    return q;
}

void dfs(int nod,int fat)
{
    w[nod]=1;
    int best=0;
    lvl[nod]=1+lvl[fat];

    t[nod]=fat;

    for(auto it:v[nod])
    {
        if(it==fat) continue;
        dfs(it,nod);
        w[nod]+=w[it];
        if(w[it]>w[best]) best=it;
    }

    if(w[nod]==1) //frunza, vom face lant nou
    {
        chains++;
        where[nod]=chains;
        ch[where[nod]].push_back(nod);
        T[chains]=fat;
        sz[chains]=1;
        pos[nod]=sz[chains];
    }
        else
    {
        where[nod]=where[best];
        ch[where[nod]].push_back(nod);
        sz[where[nod]]++;
        pos[nod]=sz[where[nod]];
    }

}

int n,q,x,y;
int offset[maxN];
int op;

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);
    }


    dfs(1,0);

    for(int i=1;i<=chains;i++)
    {
        sort(ch[i].begin(),ch[i].end(),cmp);
        T[i]=t[ch[i][0]];
        for(int j=0;j<(int)ch[i].size();j++)
            pos[ch[i][j]]=j+1;
    }


    //

    for(int i=1;i<=chains;i++)
        offset[i]=offset[i-1]+4*sz[i];

    for(int i=1;i<=chains;i++)
        build(1,1,sz[i],offset[i-1],i);

   // cerr<<ch[1][2]<<'\n';

    while(q--)
    {
        scanf("%d%d%d",&op,&x,&y);
        if(!op)
        {
            val[x]=y;
            int wx=where[x];
            update(1,1,sz[where[x]],pos[x],offset[wx-1],wx);
        }
            else
        {
            int wx=where[x];
            int wy=where[y];

            int sol=0;

            do
            {
                if(wx!=wy)
                {
                    if(lvl[T[wx]]>lvl[T[wy]])
                    {
                        sol=max(sol,query(1,1,sz[wx],1,pos[x],offset[wx-1]));
                        x=T[wx];
                        wx=where[x];
                    }
                        else
                    {
                        sol=max(sol,query(1,1,sz[wy],1,pos[y],offset[wy-1]));
                        y=T[wy];
                        wy=where[y];
                    }
                }


                if(wx==wy)
                {
                    if(pos[x]>pos[y]) swap(x,y);
                    sol=max(sol,query(1,1,sz[wx],pos[x],pos[y],offset[wx-1]));
                }
            }while(wx!=wy);

            printf("%d\n",sol);
        }
    }

    return 0;
}