Cod sursa(job #51252)

Utilizator scapryConstantin Berzan scapry Data 10 aprilie 2007 17:23:02
Problema Stramosi Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.42 kb
#include <stdio.h>
#include <string.h>

enum { maxn = 250001 };
int firstbit[maxn];

int n;
int dad[maxn];
int depth[maxn];
int ans[maxn][32]; //powers of 2 (we only need log2(E) < 19)

struct ls
{
	int n;
	ls *next;
} *lst[maxn];

void add(int from, int to)
{
	ls *p = new ls;
	p->n = to;
	p->next = lst[from];
	lst[from] = p;
}

void precalc_firstbit()
{
	int i, bit = 0;

	for(i = 0; i < maxn; i++)
	{
		if(i >= (1 << bit)) bit++;
		firstbit[i] = bit - 1;
	}
}

int calc(int node, int rank)
{
	if(rank > n) return 0;
	if(rank >= depth[node]) return 0;

	int bit;

	while(true)
	{
		if(rank == 0) return node;

		bit = firstbit[rank];

		node = ans[node][bit];
		rank &= (~(1 << bit));
	}
}

void precalc(int node)
{
	depth[node] = depth[ dad[node] ] + 1;

	for(int i = 0; i < 31; i++)
	{
		ans[node][i] = calc(dad[node], (1 << i) - 1);
		if(ans[node][i] == 0) break; //all will be zero from now on
	}

	for(ls *p = lst[node]; p; p = p->next)
		precalc(p->n);
}

int main()
{
	int queries, i, who, rank;
	FILE *fi = fopen("stramosi.in", "r"),
	     *fo = fopen("stramosi.out", "w");
	if(!fi || !fo) return 1;

	fscanf(fi, "%d%d", &n, &queries);
	for(i = 1; i <= n; i++)
	{
		fscanf(fi, "%d", &dad[i]);
		add(dad[i], i);
	}

	precalc_firstbit();

	precalc(0); //trick: roots are "kids" of zero

	for(i = 0; i < queries; i++)
	{
		fscanf(fi, "%d %d ", &who, &rank);
		fprintf(fo, "%d\n", calc(who, rank));
	}
	
	fclose(fi);
	fclose(fo);
       	return 0;
}