Cod sursa(job #983077)

Utilizator narcis_vsGemene Narcis - Gabriel narcis_vs Data 10 august 2013 18:56:07
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.16 kb
#include <fstream>
#include <vector>
 
#define In "heavypath.in"
#define Out "heavypath.out"
#define Root 1
#define IT vector< int > ::iterator
#define Nmax 100004
#define NODE (node+decalaj)
#define LeftSon (2*node)
#define RightSon (2*node+1)
using namespace std;
 
ifstream f(In);
ofstream g(Out);
 
vector< int > Tree[Nmax];///arborele dat
vector<int > el[Nmax];///nodurile care fac parte din lantul i in ordine crescatoare dupa nivel
int niv[Nmax];///nivelul nodului i
int n, ans, L, v[Nmax];///valorea nodului i,L = numarul de lanturi
int LantDim[Nmax];///dimensiunea lantului i
int nr[Nmax];///numarul de elemente al subarborelui cu radacina in i
int Lant[Nmax];///indicele lantului din care face parte nodul i
int LantFather[Nmax];///indicele tatalui nodului cu cel mai mic nivel din lantul i
int LantSum[Nmax];///suma lungimilor lanturilor 1,2,...,i-1
int pos[Nmax];///pozitia nodului i in lantul din care face parte
int nivFather[Nmax];///nivelul pe care este pozitionat LantFather[i]
class SegmentTree
{
    public :
    inline void Build(const int node,const int left,const int right,const int decalaj,int lant)
    {
        if(left == right )
        {
            aint[NODE] = v[el[lant][left]];
            return ;
        }
        int middle = (left + right)>>1;
        Build(LeftSon,left,middle,decalaj,lant);
        Build(RightSon,middle+1,right,decalaj,lant);
        aint[NODE] = max(aint[LeftSon+decalaj],aint[RightSon+decalaj]);
    }
    inline void Update(const int node,const int left,const int right,const int pos ,const int value,const int decalaj)
    {
        if(left == right )
        {
            aint[NODE] = value;
            return ;
        }
        int middle = (left + right)>>1;
        if(pos<=middle)
            Update(LeftSon,left,middle,pos,value,decalaj);
        else
            Update(RightSon,middle+1,right,pos,value,decalaj);
        aint[NODE] = max(aint[LeftSon+decalaj],aint[RightSon+decalaj]);
    }
    inline void Query(const int node,const int left,const int right,const int x ,const int y,const int decalaj)
    {
        if(x <= left && right <= y )
        {
            ans = max(ans,aint[NODE]);
            return ;
        }
        int middle = (left + right)>>1;
        if(x<=middle)
            Query(LeftSon,left,middle,x,y,decalaj);
        if(middle+1<=y)
            Query(RightSon,middle+1,right,x,y,decalaj);
    }
    private :int aint[4*Nmax];
};
inline void Erase(const int node,const int Father)
{
    IT  it, del = Tree[node].end();
    for(it = Tree[node].begin();it!=Tree[node].end(); ++it)
        if(*it==Father)
            del = it;
        else
            Erase(*it,node);
    if(del!=Tree[node].end())
        Tree[node].erase(del);
}
 
inline void DFS(const int node)
{
    IT it;
    bool frunza = 1;
    int SonMAX = 0, lant;
    nr[node] = 1;
    for(it = Tree[node].begin(); it!= Tree[node].end(); ++it)
    {
        niv[*it] = niv[node]+1;
        frunza = 0;
        DFS(*it);
        nr[node] += nr[*it];
        if(nr[*it] > nr[SonMAX])
            SonMAX= *it;
    }
    if(frunza)
    {
        ++L;
        Lant[node] = L;
        LantDim[L] = 1;
        el[L].push_back(node);
        return ;
    }
    ///punem nodul pe lantul fiului cu cele mai multe noduri in subarbore
    lant = Lant[SonMAX];
    Lant[node] = lant;
    ++LantDim[lant];
    el[lant].push_back(node);
    for(it = Tree[node].begin(); it!= Tree[node].end(); ++it)
        if(*it!=SonMAX)
        {
            LantFather[Lant[*it]] = node;
            nivFather[Lant[*it]] = niv[node];
        }
}
 
inline void Reverse(const int i)
{
    int j,n = LantDim[i],m;
    m =  (n>>1)+ (n&1);
    if(n==1)
        pos[el[i][1]] = 1;
    for(j = 1;j <= m; ++j)
    {
        swap(el[i][j],el[i][n-j+1]);
        pos[el[i][j]] = j;
        pos[el[i][n-j+1]] = n-j+1;
    }
}
SegmentTree A;
int main()
{
    int i,x, y, m, t;
    f>>n>>m;
    for(i = 1;i <= n; ++i)
        f>>v[i];
    for(i = 1;i < n; ++i)
    {
        f>>x>>y;
        el[i].push_back(0);
        Tree[x].push_back(y);
        Tree[y].push_back(x);
    }
    Erase(Root,0);
    niv[Root] = 1;
    DFS(Root);
    for(i = 1;i <= L; ++i)
    {
        Reverse(i);
        if(i>1)
            LantSum[i] = LantSum[i-1] + 4*LantDim[i-1];
        A.Build(1,1,LantDim[i],LantSum[i],i);
    }
    for( ; m; --m)
    {
        f>>t>>x>>y;
        if(!t)
            A.Update(1,1,LantDim[Lant[x]],pos[x],y,LantSum[Lant[x]]);
        else
        {
            ans = 0;
            while(true)
            {
                if(Lant[x]==Lant[y])
                {
                    if(niv[x]>niv[y])
                        swap(x,y);
                    A.Query(1,1,LantDim[Lant[x]],pos[x],pos[y],LantSum[Lant[x]]);
                    break;
                }
                if(nivFather[Lant[x]] < nivFather[Lant[y]])
                    swap(x,y);
                A.Query(1,1,LantDim[Lant[x]],1,pos[x],LantSum[Lant[x]]);
                x = LantFather[Lant[x]];
            }
            g<<ans<<"\n";
        }
    }
    f.close();
    g.close();
    return 0;
}