Cod sursa(job #1416879)

Utilizator chiriacandrei25Chiriac Andrei chiriacandrei25 Data 9 aprilie 2015 02:03:54
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.51 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#define Nmax 500005
#define INF 2000000000
#define pb push_back

using namespace std;

int n,val[Nmax],NrPaths,Nr[Nmax],Path[Nmax],Pos[Nmax],Father[Nmax],Lvl[Nmax],Len[Nmax],values[Nmax];
vector <int> Tree[Nmax],Paths[Nmax];

class SegmentTree
{
public :
    vector <int> aint;
    inline void Build(int nod, int st, int dr)
    {
        if(st==dr)
        {
            aint[nod]=values[st];
            return;
        }
        int mij=((st+dr)>>1);
        Build(2*nod,st,mij);
        Build(2*nod+1,mij+1,dr);
        aint[nod]=max(aint[2*nod],aint[2*nod+1]);
    }

    inline void Update(int nod, int st, int dr, int x, int y)
    {
        if(st==dr)
        {
            aint[nod]=y;
            return;
        }
        int mij=((st+dr)>>1);
        if(x<=mij)
            Update(2*nod,st,mij,x,y);
        else
            Update(2*nod+1,mij+1,dr,x,y);
        aint[nod]=max(aint[2*nod],aint[2*nod+1]);
    }

    inline int Query(int nod, int st, int dr, int x, int y)
    {
        if(st==x && y==dr)
            return aint[nod];
        int mij=((st+dr)>>1);
        if(y<=mij)
            return Query(2*nod,st,mij,x,y);
        else
            if(x>mij)
                return Query(2*nod+1,mij+1,dr,x,y);
            else
                return max(Query(2*nod,st,mij,x,mij),Query(2*nod+1,mij+1,dr,mij+1,y));
    }
private :
};
SegmentTree STrees[Nmax];

inline void Dfs1(int nod, int tata, int level)
{
    Nr[nod]=1; Lvl[nod]=level;
    int node=0;
    for(auto it : Tree[nod])
        if(it!=tata)
        {
            Dfs1(it,nod,level+1);
            Nr[nod]+=Nr[it];
            if(Nr[it]>Nr[node]) node=it;
        }
    if(!node)
    {
        ++NrPaths;
        Paths[NrPaths].push_back(nod);
        Path[nod]=NrPaths;
    }
    else
    {
        Path[nod]=Path[node];
        Paths[Path[node]].push_back(nod);
    }
}

inline void Dfs2(int nod, int tata)
{
    for(auto it : Tree[nod])
    {
        if(it==tata) continue;
        if(Path[it]!=Path[nod])
            Father[Path[it]]=nod;
        Dfs2(it,nod);
    }
}

int main()
{
    int i,x,y,Q,tip,sol;
    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);
        Tree[x].push_back(y);
        Tree[y].push_back(x);
    }
    Dfs1(1,0,1);
    for(i=1;i<=NrPaths;++i)
    {
        reverse(Paths[i].begin(),Paths[i].end());
        int len=0;
        for(int j=0;j<Paths[i].size();++j)
        {
            Pos[Paths[i][j]]=j+1;
            values[++len]=val[Paths[i][j]];
        }
        STrees[i].aint.resize(4*len+5);
        STrees[i].Build(1,1,len);
        Len[i]=len;
        Paths[i].clear();
    }
    Dfs2(1,0);
    while(Q--)
    {
        scanf("%d%d%d", &tip,&x,&y);
        if(!tip) STrees[Path[x]].Update(1,1,Len[Path[x]],Pos[x],y);
        else
        {
            sol=-INF;
            while(Path[x]!=Path[y])
            {
                if(Lvl[Father[Path[x]]]<Lvl[Father[Path[y]]]) swap(x,y);
                sol=max(sol,STrees[Path[x]].Query(1,1,Len[Path[x]],1,Pos[x]));
                x=Father[Path[x]];
            }
            int l1=min(Pos[x],Pos[y]),l2=max(Pos[x],Pos[y]);
            sol=max(sol,STrees[Path[x]].Query(1,1,Len[Path[x]],l1,l2));
            printf("%d\n", sol);
        }
    }
    return 0;
}