Cod sursa(job #1463218)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 20 iulie 2015 15:43:59
Problema Heavy Path Decomposition Scor 100
Compilator c Status done
Runda Arhiva educationala Marime 3.6 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 100000
int k, val[2*MAXN-1], next[2*MAXN-1], lista[MAXN+1];
int t, *aint[MAXN+1], cati[MAXN+1], father[MAXN+1];
int schimb, acum, begin, end, unde, maxim;
int q[MAXN+1], fiuMare[MAXN+1], dad[MAXN+1], h[MAXN+1], hmax[MAXN+1], sum[MAXN+1], poz[MAXN+1], path[MAXN+1];
inline int max2(int a, int b){
    if(a>b){
        return a;
    }
    return b;
}
inline void swap(int *a, int *b){
    int aux=(*a);
    (*a)=(*b);
    (*b)=aux;
}
inline void adauga(int x, int y){
    k++;
    val[k]=y;
    next[k]=lista[x];
    lista[x]=k;
}
void dfs(int tata, int nod){
    int p=lista[nod];
    fiuMare[nod]=0;
    dad[nod]=tata;
    h[nod]=h[tata]+1;
    sum[nod]=1;
    while(p){
        if(val[p]!=tata){
            dfs(nod, val[p]);
            sum[nod]+=sum[val[p]];
            if(sum[fiuMare[nod]]<sum[val[p]]){
                fiuMare[nod]=val[p];
            }
        }
        p=next[p];
    }
    if(fiuMare[nod]){
        hmax[nod]=hmax[fiuMare[nod]];
    }else{
        hmax[nod]=h[nod];
    }
}
void HPD(int nod){
    int acum, cine, i, p;
    t++;
    acum=t;
    cati[acum]=(hmax[nod]-h[nod]+1);
    aint[acum]=malloc(4*cati[acum]*sizeof(int));
    //memset(aint[acum], 0, 4*cati[acum]*sizeof(int));
    father[acum]=dad[nod];
    cine=nod;
    for(i=0; i<cati[acum]; i++){
        poz[cine]=i;
        path[cine]=acum;
        p=lista[cine];
        while(p){
            if((val[p]!=dad[cine])&&(val[p]!=fiuMare[cine])){
                HPD(val[p]);
            }
            p=next[p];
        }
        cine=fiuMare[cine];
    }
}
void update(int p, int st, int dr){
    if(st==dr){
        aint[acum][p]=schimb;
        return ;
    }
    int m=(st+dr)/2;
    if(m>=unde){
        update(2*p+1, st, m);
    }else{
        update(2*p+2, m+1, dr);
    }
    aint[acum][p]=max2(aint[acum][2*p+1], aint[acum][2*p+2]);
}
void query(int p, int st, int dr){
    if((begin<=st)&&(dr<=end)){
        maxim=max2(maxim, aint[acum][p]);
        return ;
    }
    int m=(st+dr)/2;
    if(begin<=m){
        query(2*p+1, st, m);
    }
    if(end>=m+1){
        query(2*p+2, m+1, dr);
    }
}
int main(){
    int n, m, i, x, y, a, b, c;
    FILE *fin, *fout;
    fin=fopen("heavypath.in", "r");
    fout=fopen("heavypath.out", "w");
    fscanf(fin, "%d%d", &n, &m);
    for(i=1; i<=n; i++){
        fscanf(fin, "%d", &q[i]);
    }
    for(i=1; i<n; i++){
        fscanf(fin, "%d%d", &x, &y);
        adauga(x, y);
        adauga(y, x);
    }
    dfs(0, 1);
    HPD(1);
    for(i=1; i<=n; i++){
        acum=path[i];
        schimb=q[i];
        unde=poz[i];
        update(0, 0, cati[path[i]]-1);
    }
    for(i=0; i<m; i++){
        fscanf(fin, "%d%d%d", &a, &b, &c);
        if(a==0){
            acum=path[b];
            schimb=c;
            unde=poz[b];
            update(0, 0, cati[path[b]]-1);
        }else{
            maxim=0;
            while(path[b]!=path[c]){
                if(h[father[path[b]]]<h[father[path[c]]]){
                    swap(&b, &c);
                }
                acum=path[b];
                begin=0;
                end=poz[b];
                query(0, 0, cati[path[b]]-1);
                b=father[path[b]];
            }
            acum=path[b];
            begin=poz[b];
            end=poz[c];
            if(begin>end){
                swap(&begin, &end);
            }
            query(0, 0, cati[path[b]]-1);
            fprintf(fout, "%d\n", maxim);
        }
    }
    fclose(fin);
    fclose(fout);
    return 0;
}