Cod sursa(job #2445806)

Utilizator AndreiStanescuAlloys Nokito AndreiStanescu Data 5 august 2019 16:08:15
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.26 kb
#include<bits/stdc++.h>
#define dim_max 1800001
#define nmax 100001

using namespace std;

//matricea arborelui

int n,v[nmax],m;

vector<int> G[nmax],T[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;

};

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];

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

{

    int mij=(st+dr)/2;

    if(st==dr)

            {SegTree[nod]=Arb[st];

            return SegTree[nod];

            }

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

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



    else

    {
        SegTree[nod]=max(ConstrArb(nod*2,st,mij),ConstrArb(nod*2+1,mij+1,dr));
        return SegTree[nod];


    }

}



//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 size,euler[dim_max],lev[dim_max],Pos[nmax];
int lookup[dim_max][18];

void Euler_tour(int nod,int level)
{
    euler[size]=nod;
    lev[size]=level;
    Pos[nod]=size;
    ++size;
    vector<int>::iterator it;
    for(it=T[nod].begin();it!=T[nod].end();it++)
    {
        Euler_tour(*it,level+1);
        euler[size]=nod;
        lev[size]=level;
        ++size;

    }

}


void preprocess(int arr[],int k)
{
    int i,j;
    //initializare
    for(i=0;i<k;i++)
        lookup[i][0]=i;

    for(j=1;(1<<j)<k;j++)
    for(i=0;i+(1<<j)-1<k;i++)
    if(arr[lookup[i][j-1]]<=arr[lookup[i+(1<<(j-1))][j-1]])
    lookup[i][j]=lookup[i][j-1];
    else
        lookup[i][j]=lookup[i+(1<<(j-1))][j-1];

}

int lca(int nod1,int nod2)
{
    int l,r,dim;
    l=Pos[nod1];
    r=Pos[nod2];
    if(l>r) swap(l,r);
    dim=(int)log2(r-l+1);
    if(lev[lookup[l][dim]]<=lev[lookup[r-(1<<dim)+1][dim]])
        return euler[lookup[l][dim]];
    else
        return euler[lookup[r-(1<<dim)+1][dim]];

}




//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_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(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;
        G[a].push_back(b);
        G[b].push_back(a);
        T[a].push_back(b);
    }
    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;

    Euler_tour(root,0);
    preprocess(lev,size);

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

}