Cod sursa(job #995367)

Utilizator dutzulBodnariuc Dan Alexandru dutzul Data 8 septembrie 2013 19:28:06
Problema Heavy Path Decomposition Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 4.8 kb
#include <iostream>
#include <fstream>
using namespace std;
ifstream f("heavypath.in");
ofstream g("heavypath.out");

#define LE 100666
#include <vector>
vector<int> H[LE];
#define pb push_back

int n,nrq,i;
bool viz[LE];
int level[LE],lant_ind[LE],lant_pos[LE],lant_up[LE];
int st[LE*3];
vector<int> Arb[LE];
int father[LE],fap[LE*3];
int rmq[17][LE],k,Arb_sum[LE],val[LE];
int mpow[LE],nr_lant,grad[LE];

void dfs(int nod,int lev) {
    viz[nod]=true;
    level[nod]=lev;
    int N=H[nod].size(),i;
    fap[nod]=++k;
    st[k]=nod;
    Arb_sum[nod]=1;

    for(i=0; i<N; ++i)
        if (viz[H[nod][i]]==false) {
            dfs(H[nod][i],lev+1);
            st[++k]=nod;
            Arb_sum[nod]+=Arb_sum[H[nod][i]];
            father[H[nod][i]]=nod;
        }
}

int get_lca(int nod1,int nod2) {
    int x1=fap[nod1],x2=fap[nod2];
    if (x1>x2) swap(x1,x2);

    int D=x2-x1+1;
    int P=mpow[D];

    if (level[rmq[P][x1]]<level[rmq[P][x2-(1<<P)+1]])
        return rmq[P][x1];
    else return rmq[P][x2-(1<<P)+1];
}


void heavy_path(int nod) {
    viz[nod]=true;
    int N=H[nod].size(),i;
    int max_nodes=0,node_unite;

    for(i=0; i<N; ++i)
        if (viz[H[nod][i]]==false) {
            heavy_path(H[nod][i]);
            if (Arb_sum[H[nod][i]]>max_nodes) {
                max_nodes=Arb_sum[H[nod][i]];
                node_unite=H[nod][i];
            }
        }
    if (max_nodes==0) {
        ++nr_lant;
        lant_ind[nod]=nr_lant;
        lant_pos[nod]=1;
        grad[nr_lant]=1;

    } else {
        ++grad[lant_ind[node_unite]];
        lant_ind[nod]=lant_ind[node_unite];
        lant_pos[nod]=grad[lant_ind[node_unite]];
    }
}

void update_arb(int Vnod,int i_arb,int i_pos,int st,int dr,int nod) {

    int mij=(st+dr)/2;

    if (st==dr) {
      Arb[i_arb][nod]=Vnod;
      return;
     }

    if (i_pos<=mij) update_arb(Vnod,i_arb,i_pos,st,mij,nod*2);
    else update_arb(Vnod,i_arb,i_pos,mij+1,dr,nod*2+1);

    if (val[Arb[i_arb][nod*2]]>val[Arb[i_arb][nod*2+1]])
      Arb[i_arb][nod]=Arb[i_arb][nod*2];
      else Arb[i_arb][nod]=Arb[i_arb][nod*2+1];
}
int result,res_ind;

void query_arb(int X,int Y,int i_arb,int st,int dr,int nod) {
    int mij=(st+dr)/2;

    if (st>=X&&dr<=Y) {
        if (val[Arb[i_arb][nod]]>result) {
            result=val[Arb[i_arb][nod]];
            res_ind=Arb[i_arb][nod];
        }
        return ;
    }

    if (X<=mij) query_arb(X,Y,i_arb,st,mij,nod*2);
    if (Y>mij) query_arb(X,Y,i_arb,mij+1,dr,nod*2+1);
}

void update(int nod,int value) {
    int _lant=lant_ind[nod];
    int _pos=lant_pos[nod];
    update_arb(nod,_lant,_pos,1,grad[_lant],1);
}

int query(int nod1,int nod_root) {

    int fin_res=0,fin_ind=0;

    while (true) {

        if (lant_ind[nod1]==lant_ind[nod_root]) {
            result=res_ind=0;
            int x1=lant_pos[nod1],x2=lant_pos[nod_root];
            if  (x1>x2) swap(x1,x2);
            query_arb(x1,x2,lant_ind[nod1],1,grad[lant_ind[nod1]],1);
            if (result>=fin_res) {
                fin_res=result;
                fin_ind=res_ind;
            }
            return fin_ind;
        }

        result=res_ind=0;
        int x2=grad[lant_ind[nod1]],x1=lant_pos[nod1];
        query_arb(x1,x2,lant_ind[nod1],1,grad[lant_ind[nod1]],1);
        if (result>fin_res) {
            fin_res=result;
            fin_ind=res_ind;
        }
        nod1=father[lant_up[lant_ind[nod1]]];
    }
}

int main() {

    f>>n>>nrq;
    for(i=1; i<=n; ++i) f>>val[i];
    for(i=1; i<n; ++i) {
        int xx,yy;
        f>>xx>>yy;
        H[xx].pb(yy);
        H[yy].pb(xx);
    }

    dfs(1,1);

    for(i=1; i<=k; ++i) rmq[0][i]=st[i];

    for(int lgs=1; (1<<(lgs))<=k; lgs++)
        for(int j=1; j<=k; ++j) {

            if (j+(1<<(lgs-1))>k) {
                rmq[lgs][j]=rmq[lgs-1][j];
                continue;
            }

            if (level[rmq[lgs-1][j]]<level[rmq[lgs-1][j+(1<<(lgs-1))]])
                rmq[lgs][j]=rmq[lgs-1][j];
            else rmq[lgs][j]=rmq[lgs-1][j+(1<<(lgs-1))];
        }



    for(i=2; i<=k; ++i) mpow[i]=mpow[i/2]+1;
    for(i=1; i<=n; ++i) viz[i]=false;

    heavy_path(1);
//       cout<<get_lca(6 ,9);
//cout<<get_lca(1,9)<<'\n';

    //for(i=1; i<=n; ++i) cout<<lant_ind[i]<<" ";

    for(i=1; i<=nr_lant; ++i)
        for(int j=1; j<=grad[i]*5; ++j) Arb[i].pb(0);

    for(i=1; i<=n; ++i)
        update(i,val[i]);

    for(i=1; i<=n; ++i)
        if (lant_pos[i]==grad[lant_ind[i]]) lant_up[lant_ind[i]]=i;

//cout<<nrq<<'\n';

    for(int tt=1; tt<=nrq; ++tt) {
        int tip,v1,v2;
        f>>tip>>v1>>v2;
        if (tip==0) {
        val[v1]=v2;
            update(v1,v2);
        } else  {
            int nod1=query(v1,get_lca(v1,v2));
            int nod2=query(v2,get_lca(v1,v2));
            if (val[nod1]>val[nod2]) g<<val[nod1];
            else g<<val[nod2];
            g<<'\n';
        }
    }

    f.close();
    g.close();
    return 0;
}