Cod sursa(job #1555595)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 23 decembrie 2015 11:18:27
Problema Lowest Common Ancestor Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 4.11 kb
#include <cstdio>
#include <cctype>
#define BUF_SIZE 4096
#define MAXN 100000
#define MAXU (2*MAXN-1)
#define LOGU 17
//#define MAGIC (int)(LOGU/2)
#define MAGIC 11
int m, u, l;
int lista[MAXN+1], next[MAXN], val[MAXN], e[MAXU+1], h[MAXN+1], f[MAXN+1], lg[MAXU+1], rmq[MAGIC][MAXU/MAGIC+1], t[MAXU/MAGIC+2], v[MAGIC];
int r[1<<(MAGIC-1)][MAGIC][MAGIC];
int poz=BUF_SIZE, pos=0;
char buf[BUF_SIZE], buf2[BUF_SIZE], c[10];
FILE *fin, *fout;
inline char nextch(){
    if(poz==BUF_SIZE){
        fread(buf, BUF_SIZE, 1, fin);
        poz=0;
    }
    return buf[poz++];
}
inline int read(){
    int x=0;
    char ch=nextch();
    while(!isdigit(ch)){
        ch=nextch();
    }
    while(isdigit(ch)){
        x=10*x+ch-'0';
        ch=nextch();
    }
    return x;
}
inline void putch(char ch){
    buf2[pos++]=ch;
    if(pos==BUF_SIZE){
        fwrite(buf2, BUF_SIZE, 1, fout);
        pos=0;
    }
}
inline void baga(int x){
    int k=0;
    do{
        c[k++]=x%10+'0';
        x/=10;
    }while(x>0);
    while(k){
        k--;
        putch(c[k]);
    }
}
inline void adauga(int x, int y){
    m++;
    val[m]=y;
    next[m]=lista[x];
    lista[x]=m;
}
void dfs(int x){
    int p=lista[x];
    u++;
    e[u]=x;
    f[x]=u;
    while(p){
        if(h[val[p]]==0){
            h[val[p]]=h[x]+1;
            dfs(val[p]);
        }
        u++;
        e[u]=x;
        p=next[p];
    }
}
inline void makeLog(){
    int i;
    for(i=2; i<=u; i++){
        lg[i]=lg[i>>1]+1;
    }
}
inline void makeRmq(){
    int i, j, p, a, b;
    l=MAGIC;
    p=1;
    for(i=1; i<=u/l; i++){
        t[i]=0;
        rmq[0][i]=e[p++];
        for(j=1; j<l; j++){
            if(h[e[p]]<rmq[0][i]){
                rmq[0][i]=e[p];
            }
            if(h[e[p]]>h[e[p-1]]){
                t[i]+=1<<(j-1);
            }
            p++;
        }
    }
    p++;
    j=0;
    while(p<=u){
        if(h[e[p]]>h[e[p-1]]){
            t[i]+=1<<j;
        }
        p++;
        j++;
    }
    for(i=1; (1<<i)<=u/l; i++){
        for(j=1; j<=u/l; j++){
            if(h[rmq[i-1][j]]<h[rmq[i-1][j-(1<<(i-1))]]){
                rmq[i][j]=rmq[i-1][j];
            }else{
                rmq[i][j]=rmq[i-1][j-(1<<(i-1))];
            }
        }
    }
    for(i=0; i<(1<<(l-1)); i++){
        v[0]=0;
        for(j=0; j<l-1; j++){
            if((1<<j)&i){
                v[j+1]=v[j]+1;
            }else{
                v[j+1]=v[j]-1;
            }
        }
        for(a=0; a<l; a++){
            r[i][a][a]=a;
            for(b=a+1; b<l; b++){
                if(v[r[i][a][b-1]]<v[b]){
                    r[i][a][b]=r[i][a][b-1];
                }else{
                    r[i][a][b]=b;
                }
            }
        }
    }
}
inline void precalc(){
    h[1]=1;
    dfs(1);
    h[0]=u+1;
    makeLog();
    makeRmq();
}
inline int mare(int x, int y){
    if(x>y){
        return 0;
    }
    if(h[rmq[lg[y-x+1]][y]]<h[rmq[lg[y-x+1]][x+(1<<(lg[y-x+1]))-1]]){
        return rmq[lg[y-x+1]][y];
    }else{
        return rmq[lg[y-x+1]][x+(1<<(lg[y-x+1]))-1];
    }
}
inline int mic(int x, int y){
    return e[l*((x-1)/l)+1+r[t[(x+l-1)/l]][(x-1)%l][(y-1)%l]];
}
inline int lca(int x, int y){
    if(f[x]>f[y]){
        int aux=x;
        x=y;
        y=aux;
    }
    if((f[y]-1)/l==(f[x]-1)/l){
        return mic(f[x], f[y]);
    }
    int a=mic(f[x], l*((f[x]+l-1)/l)), b=mare((f[x]+l-1)/l+1, (f[y]-1)/l), c=mic(l*((f[y]-1)/l)+1, f[y]);
    if(h[a]<h[b]){
        if(h[a]<h[c]){
            return a;
        }
        return c;
    }
    if(h[b]<h[c]){
        return b;
    }
    return c;
}
int main(){
    int q, i, x, y, n;
    fin=fopen("lca.in", "r");
    fout=fopen("lca.out", "w");
    n=read();
    q=read();
    for(i=2; i<=n; i++){
        adauga(read(), i);
    }
    precalc();
    for(i=1; i<=q; i++){
        x=read();
        y=read();
        baga(lca(x, y));
        putch('\n');
    }
    if(pos>0){
        fwrite(buf2, pos, 1, fout);
    }
    fclose(fin);
    fclose(fout);
    return 0;
}