Cod sursa(job #2438237)

Utilizator AndreiStanescuAlloys Nokito AndreiStanescu Data 11 iulie 2019 20:14:08
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.06 kb
#include<bits/stdc++.h>

#define nmax 100001

using namespace std;

//matricea arborelui

int n,v[nmax],m;



vector<int> G[nmax];



struct Nod

{

    int tata;

    int nivel;

    int subarb;

    int poz;

    int chain;

    int weight;

};



Nod nodes[nmax];



struct muchie

{

    int weight;

    int nod_deep;

};



muchie edges[nmax];





//adaugam o muchie, cu ID-ul e, nodurile u si v, cu greutataea w

/*void addEdge(int e,int u,int v)

{

    //arborele ca un graf neorientat

    tree[u][v]=e;

    tree[v][u]=e;

    //edges[e-1].weight=w;

}*/



int Arb[4*nmax];



void dfs(int curr,int prev,int lev)

{

    int i;

    nodes[curr].tata=prev;

    nodes[curr].nivel=lev;

    nodes[curr].subarb=1;

    //pentru toti fiii lui nodului curent

    vector<int>::iterator it;

    for(it=G[curr].begin();it!=G[curr].end();it++)

    //for(i=1;i<=n;i++)

        if((*it)!=nodes[curr].tata)

    {

        dfs((*it),curr,lev+1);

        nodes[curr].subarb+=nodes[*it].subarb;

    }



}



void hld(int curr_node,int *pos,int *curr_chain,int chain_heads[])

{

    if(chain_heads[*curr_chain]==-1)

        chain_heads[*curr_chain]=curr_node;



    nodes[curr_node].chain=*curr_chain;

    nodes[curr_node].poz=++(*pos);

    Arb[*pos]=v[curr_node];

    //cout<<curr_node<<' '<<(*pos)<<endl;



    int special=-1,j;

    vector<int>::iterator it;

    for(it=G[curr_node].begin();it!=G[curr_node].end();it++)

        if((*it)!=nodes[curr_node].tata )

        if(special==-1 || nodes[special].subarb<nodes[*it].subarb)

        special=(*it);



        //cout<<special<<' ';



    if(special!=-1)

        hld(special,pos,curr_chain,chain_heads);

    //pentru fiii normali

    for(it=G[curr_node].begin();it!=G[curr_node].end();it++)

        if((*it)!=nodes[curr_node].tata && (*it)!=special)

    {

        //cout<<curr_node<<' '<<*curr_chain<<endl;

        ++(*curr_chain);

        hld((*it),pos,curr_chain,chain_heads);

    }





}



//construiesc arborele de intervale pentru Arb

int SegTree[4*nmax];



void ConstrArb(int nod,int st,int dr)

{

    int mij=(st+dr)/2;

    if(st==dr)

            {SegTree[nod]=Arb[st];

            return;

            }

       // else //[st,dr] e inclus in a[b]

       // SegTree[nod]=max(SegTree[2*nod],SegTree[2*nod+1]);



    else

    {



            ConstrArb(nod*2,st,mij);

            ConstrArb(nod*2+1,mij+1,dr);

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



    }

}



//operatia de tip 0

void update(int nod,int st,int dr,int x,int val)

{

    //tot pe interval deschis

    if(x<st || x>dr);

    int mij=(st+dr)/2;

    if(st==x && dr==x)

    {

        SegTree[nod]=val;

            return;

    }

    else

    {

        if(x<=mij)

            update(nod*2,st,mij,x,val);

        if(x>mij)

            update(nod*2+1,mij+1,dr,x,val);

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



    }

}



int LCA(int u,int v)

{

    while(u!=v)

    {

       if(nodes[u].nivel<nodes[v].nivel)

        swap(u,v);

        u=nodes[u].tata;

    }

    return v;

}


int LCA_2(int x,int y)
{
    	while(nodes[x].tata != nodes[y].tata)
		if(nodes[x].nivel > nodes[y].nivel)
			x = nodes[x].tata;
		else
			y = nodes[y].tata;
	while(x != y)
		if(nodes[x].nivel > nodes[y].nivel)
			x = nodes[x].tata;
		else
			y = nodes[y].tata;
	return x;
}


//intoarce maximul din [a...b]

int query_1(int nod,int st,int dr,int a,int b)

{

    int mij=(st+dr)/2,c,d;

    if(a<=st && b>=dr)

        return SegTree[nod];

    if(dr<a || st>b)

        return -1;

    return max(query_1(2*nod,st,mij,a,b),query_1(2*nod+1,mij+1,dr,a,b));



}



//functia query la t=1

int crawling(int u,int z,int chain_heads[])

{

    int chain_u,chain_z,ans=0,ok=0;

    while(!ok )

    {

      chain_u=nodes[u].chain;

      chain_z=nodes[z].chain;

      if(chain_u==chain_z)

        {ans=max(ans,query_1(1,1,n,min(nodes[u].poz,nodes[z].poz),max(nodes[u].poz,nodes[z].poz)));

        ok=1;

        }

        else

        {

            ans=max(ans,max( query_1(1,1,n,nodes[chain_heads[chain_u]].poz,nodes[u].poz),query_1(1,1,n,nodes[chain_heads[chain_z]].poz,nodes[z].poz)));

            u=nodes[chain_heads[chain_u]].tata;

            z=nodes[chain_heads[chain_z]].tata;

            if(u==-1) u=1;

            if(z==-1) z=1;

            if(u==z && u==1)

            {

                ok=1;

                ans=max(ans,v[1]);

            }



        }



    }

    return ans;

}



int crawling_2(int u,int z,int chain_heads[])

{

    int chain_u,chain_z,ans=0,ok=0;

    while(!ok )

    {

      chain_u=nodes[u].chain;

      chain_z=nodes[z].chain;

      if(chain_u==chain_z)

        {ans=max(ans,query_1(1,1,n,min(nodes[u].poz,nodes[z].poz),max(nodes[u].poz,nodes[z].poz)));

        ok=1;

        }

        else

        {

            if(nodes[nodes[chain_heads[chain_z]].tata].nivel>nodes[nodes[chain_heads[chain_u]].tata].nivel)

                swap(u,z);

            ans=max(ans,query_1(1,1,n,nodes[chain_heads[chain_u]].poz,nodes[u].poz));

            u=nodes[chain_heads[chain_u]].tata;

            //z=nodes[chain_heads[chain_z]].tata;

            if(u==-1) u=1;

            //if(z==-1) z=1;



        }



    }

    return ans;



}



int max_node(int u,int v,int chain_heads[])

{

    int lca=LCA_2(u,v),ans=0;

    ans=max(crawling_2(u,lca,chain_heads),crawling_2(v,lca,chain_heads));

    return ans;

}







int main()

{

    int i,a,b,chain_heads[nmax],t;

    ifstream fin("heavypath.in");

    ofstream fout("heavypath.out");

    fin>>n>>m;

    //memset(tree,-1,sizeof(tree));

    for(i=1;i<=n;i++)

        fin>>v[i];

    memset(chain_heads,-1,sizeof(chain_heads));

    for(i=1;i<n;i++)

    {

        fin>>a>>b;

        //addEdge(i,a,b);

        G[a].push_back(b);

        G[b].push_back(a);

    }

    int edge_counted=0,curr_chain=1;

    dfs(1,-1,0);

      //for(i=1;i<=n;i++)

       // cout<<nodes[i].subarb<<' ';



    hld(1,&edge_counted,&curr_chain,chain_heads);



    //cout<<endl;

    //for(i=1;i<=pos;i++)

      // cout<<Arb[i]<<' ';

    int root=1;

    ConstrArb(root,1,n);

    root=1;

    //cout<<SegTree[5];



    //cout<<nodes[9].poz;

    //cout<<update(root,1,n+1,nodes[3].poz,1);



    //for(i=1;i<=curr_chain;i++)

        //cout<<chain_heads[i]<<' ';



    for(i=1;i<=m;i++)

    {

        fin>>t>>a>>b;

        if(!t)

            update(1,1,n,nodes[a].poz,b);

        if(t==1)

            fout<<max_node(a,b,chain_heads)<<'\n';



    }

    fin.close();

    fout.close();

    //cout<<LCA(4,5);

    //cout<<query_1(1,1,n+1,3,3);





}