Cod sursa(job #1146157)

Utilizator oprea1si2si3Oprea Sebastian oprea1si2si3 Data 18 martie 2014 19:18:40
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.71 kb
#include<fstream>
#include<iostream>
#include<vector>
#include<algorithm>
#define MAXN  100010
using namespace std;

ifstream in("heavypath.in");
ofstream out("heavypath.out");

vector <int> Muchie[MAXN],LantElementar[MAXN];
int N,M,Valoare[MAXN];
int viz[MAXN],fii[MAXN],nivel[MAXN],lant[MAXN];
int NumarSiruri,tata[MAXN],ArbInt[4*MAXN],poz[MAXN];


void Citire_Graf() {

    int i,x,y;
    in>>N>>M;
    for(i=1;i<=N;i++)
        in>>Valoare[i];
    for(i=1;i<=N-1;i++) {
        in>>x>>y;
        Muchie[x].push_back(y);
        Muchie[y].push_back(x);
    }
}

void dfs(int nod) {

    int i,vecin,best=-1;
    viz[nod]=1;
    fii[nod]=1;
    for(i=0;i<Muchie[nod].size();i++) {
        vecin=Muchie[nod][i];
        if(viz[vecin]==0) {
            nivel[vecin]=nivel[nod]+1;
            dfs(vecin);
            fii[nod]+=fii[vecin];
            if(best==-1 || fii[best]<fii[vecin])
                best=vecin;
        }
    }
    if(fii[nod]==1) {
        NumarSiruri++;
        lant[nod]=NumarSiruri;
        LantElementar[NumarSiruri].push_back(nod);
        return;
    }
    lant[nod]=lant[best];
    LantElementar[lant[nod]].push_back(nod);
    for(i=0;i<Muchie[nod].size();i++){
        vecin=Muchie[nod][i];
        if(vecin!=best)
            tata[lant[vecin]]=nod;
    }

}

void Construire(int nod,int st,int dr,int lant,int decalaj) {
    int mij;
    if(st==dr) {
        ArbInt[nod+decalaj]=Valoare[LantElementar[lant][st-1]];
        return;
    }
    mij=(st+dr)/2;
    Construire(2*nod,st,mij,lant,decalaj);
    Construire(2*nod+1,mij+1,dr,lant,decalaj);
    ArbInt[nod+decalaj]=max(ArbInt[2*nod+decalaj],ArbInt[2*nod+1+decalaj]);

}

void Creere_Drumuri() {

    int i;
    nivel[1]=1;
    dfs(1);

    for(i=1;i<=NumarSiruri;i++) {
        reverse(LantElementar[i].begin(),LantElementar[i].end());
        poz[i]=poz[i-1]+(LantElementar[i-1].size()*4);
        Construire(1,1,LantElementar[i].size(),i,poz[i]);
    }

}

void Initializare() {
    Citire_Graf();
    Creere_Drumuri();
}

void Actualizare(int nod,int st,int dr,int val,int poz,int decalaj) {

    int mij;
    if(st==dr){
        ArbInt[nod+decalaj]=val;
        return ;
    }
    mij=(st+dr)/2;
    if(poz<=mij)
        Actualizare(2*nod,st,mij,val,poz,decalaj);
    else
        Actualizare(2*nod+1,mij+1,dr,val,poz,decalaj);
    ArbInt[nod+decalaj]=max(ArbInt[2*nod+decalaj],ArbInt[2*nod+1+decalaj]);

}

int interogare (int nod,int st,int dr,int a,int b,int decalaj) {

    int mij,partial=0;
    if(a<=st&&dr<=b)
        return ArbInt[nod+decalaj];
    mij=(st+dr)/2;
    if(a<=mij)
        partial=interogare(2*nod,st,mij,a,b,decalaj);
    if(b>mij)
        partial=max(partial,interogare(2*nod+1,mij+1,dr,a,b,decalaj));
    return partial;
}

int MaxLant(int x,int y) {

    int sol;
    sol=0;
    while(lant[x]!=lant[y]) {
        if(nivel[tata[lant[x]]]<nivel[tata[lant[y]]])
            swap(x,y);
        sol=max(sol,interogare(1,1,LantElementar[lant[x]].size(),1,nivel[x]-nivel[tata[lant[x]]],poz[lant[x]]));
        x=tata[lant[x]];
    }
    if(nivel[x]>nivel[y])
        swap(x,y);
    sol=max(sol,interogare(1,1,LantElementar[lant[x]].size(),nivel[x]-nivel[tata[lant[x]]],nivel[y]-nivel[tata[lant[y]]], poz[lant[x]] ));
    return sol;

}

void Solve() {

    int i,tip,x,y;
    for(i=1;i<=M;i++) {
        in>>tip>>x>>y;
        if(tip==0){
            Actualizare(1,1,LantElementar[lant[x]].size(),y,nivel[x]-nivel[tata[lant[x]]],poz[lant[x]]);
        }
        if(tip==1){
            out<<MaxLant(x,y)<<'\n';
        }
    }
    in.close();
    out.close();

}

int main() {

    Initializare();
    Solve();
    return 0;

}