Cod sursa(job #1453043)

Utilizator chiriacandrei25Chiriac Andrei chiriacandrei25 Data 22 iunie 2015 17:26:57
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.04 kb
#include <fstream>
#include <vector>
#include <algorithm>
#define Nmax 100005
#define INF 2000000000
#define pb push_back

using namespace std;
ofstream cout ("heavypath.out");

vector <int> Tree[Nmax],Paths[Nmax];
int Val[Nmax],Path[Nmax],Father[Nmax],Len[Nmax],Pos[Nmax],Lvl[Nmax],Nr[Nmax],aux,n;

class SegmTree
{
public:
    vector <int> Aint;
    inline void Update(int nod, int st, int dr, int p, int val)
    {
        if(st==dr)
        {
            Aint[nod]=val;
            return;
        }
        int mij=((st+dr)>>1);
        if(p<=mij) Update((nod<<1),st,mij,p,val);
        else Update((nod<<1)+1,mij+1,dr,p,val);
        Aint[nod]=max(Aint[(nod<<1)],Aint[(nod<<1)+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((nod<<1),st,mij,x,y);
        else
            if(x>mij) return Query((nod<<1)+1,mij+1,dr,x,y);
        return max(Query((nod<<1),st,mij,x,mij),Query((nod<<1)+1,mij+1,dr,mij+1,y));
    }
private:
} STrees[Nmax];

inline void Dfs(int nod, int tata, int level)
{
    Lvl[nod]=level;
    int ok=0;
    int node=0;
    Nr[nod]=1;
    for(auto it : Tree[nod])
    {
        if(it==tata) continue;
        ok=1;
        Dfs(it,nod,level+1);
        Nr[nod]+=Nr[it];
        if(Nr[it]>Nr[node]) node=it;
    }
    if(!ok)
    {
        Path[nod]=++aux;
        Paths[aux].pb(nod);
        return;
    }
    Path[nod]=Path[node]; Paths[Path[node]].pb(nod);
}

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

inline void Init()
{
    int i;
    for(i=1;i<=aux;++i)
    {
        reverse(Paths[i].begin(),Paths[i].end());
        int kkt=0;
        for(auto it : Paths[i]) Pos[it]=++kkt;
        Len[i]=Paths[i].size();
        STrees[i].Aint.resize(3*Len[i]+10);
        for(int j=0;j<STrees[i].Aint.size();++j) STrees[i].Aint[j]=0;
    }
    for(i=1;i<=n;++i)
        STrees[Path[i]].Update(1,1,Len[Path[i]],Pos[i],Val[i]);
}

int main()
{
    int i,x,y,t,sol,m;
    ifstream cin ("heavypath.in");
    cin>>n>>m;
    for(i=1;i<=n;++i) cin>>Val[i];
    for(i=1;i<n;++i)
    {
        cin>>x>>y;
        Tree[x].pb(y);
        Tree[y].pb(x);
    }
    Dfs(1,0,0);
    Dfs1(1,0);
    Init();
    while(m--)
    {
        cin>>t>>x>>y;
        if(!t) STrees[Path[x]].Update(1,1,Len[Path[x]],Pos[x],y);
        else
        {
            int 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));
            cout<<sol<<"\n";
        }
    }
    return 0;
}