Cod sursa(job #51235)

Utilizator scapryConstantin Berzan scapry Data 10 aprilie 2007 16:01:54
Problema Stramosi Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.16 kb
#include <assert.h>
#include <stdio.h>
#include <string.h>

enum { maxn = 250001 };

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

int calc(int node, int rank)
{
	if(node == 0) return 0;
	if(rank == 0) return node;
	assert(rank > 0);
	assert(node > 0 && node <= n);

	int bit;
	for(bit = 0; bit < 32 && (1 << bit) <= rank; bit++);
	bit--;
	
	assert(rank & (1 << bit));

	return calc( ans[node][bit], rank & (~(1 << bit)) );
}

void precalc(int node)
{
	if(v[node]) return;

	//terminal case - root
	if(dad[node] != 0)
	{
		if(!v[ dad[node] ]) precalc(dad[node]);

		assert(v[ dad[node] ]);

		for(int i = 0; i < 31; i++)
			ans[node][i] = calc(dad[node], (1 << i) - 1);
	}

	v[node] = true;
}

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]);

	for(i = 1; i <= n; i++)
		precalc(i);

	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;
}