Cod sursa(job #2438227)

Utilizator AndreiStanescuAlloys Nokito AndreiStanescu Data 11 iulie 2019 19:40:04
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 6.23 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;
}

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


}