Cod sursa(job #2249475)

Utilizator TincaMateiTinca Matei TincaMatei Data 29 septembrie 2018 22:15:52
Problema Stramosi Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.32 kb
#include <bits/stdc++.h>

struct Tree {
	int N;
	std::vector<std::vector<int> > G;
	
	// Basic tree statistics
	int *label;
	int *subarb, *depth;
	int lastStatisticRoot;

	Tree(int _N) : N(_N) {
		G.resize(1+N);
		label = subarb = depth = NULL;
		lastStatisticRoot = 0;
	}

	void pushEdge(int a, int b) {
		G[a].push_back(b);
		G[b].push_back(a);
	}
	
	void statisticDfs(int root = 1, int father = 0) {
		subarb[root] = 1;
		for(auto it: G[root])
			if(it != father) {
				depth[it] = depth[root] + 1;
				statisticDfs(it, root);
				subarb[root] += subarb[it];
			}
	}

	void calculateStatistics(int root = 1) {
		if(subarb == NULL && depth == NULL) {
			subarb = new int[1+N];
			depth = new int[1+N];
		}

		if(lastStatisticRoot != root) {
			memset(subarb, 0, sizeof(int) * (1 + N));
			memset(depth,  0, sizeof(int) * (1 + N));
	
			statisticDfs(root);
		
			lastStatisticRoot = root;
		}
	}

	void allocLabels() {
		if(label == NULL)
			label = new int[1+N];
		memset(label, 0, sizeof(int) * (1 + N));
	}
};

struct BinaryLifting {
	Tree *T;
	int maxlg, lastRoot;
	int **ancestor;

	BinaryLifting(Tree *_T):T(_T) {
		maxlg = 0;
		while((1 << maxlg) < T->N)
			++maxlg;
		
		ancestor = new int*[1+maxlg];
		for(int i = 0; i <= maxlg; ++i)
			ancestor[i] = new int[1 + T->N];
		
		lastRoot = 0;
	}

	void ancestryDfs(int nod, int papa = 0) {
		for(auto it: T->G[nod])
			if(it != papa) {
				ancestor[0][it] = nod;
				ancestryDfs(it, nod);
			}
		for(int i = 1; i <= maxlg; ++i)
			ancestor[i][nod] = ancestor[i - 1][ancestor[i - 1][nod]];
	}

	void computeAncestry(int root = 1) {
		if(lastRoot != root) {
			lastRoot = root;
			ancestor[0][root] = 0;
			ancestryDfs(1);
		}
	}

	int goUp(int nod, int x) {
		if(x >= T->N)
			return 0;
		for(int i = 0; i <= maxlg; ++i)
			if((1 << i) & x)
				nod = ancestor[i][nod];
		return nod;
	}
};

int main() {
	FILE *fin = fopen("stramosi.in", "r");
	FILE *fout = fopen("stramosi.out", "w");
	int n, q;
	Tree *T;
	BinaryLifting *bl;

	fscanf(fin, "%d%d", &n, &q);
	T = new Tree(1+n);

	for(int i = 2; i <= n + 1; ++i) {
		int x;
		fscanf(fin, "%d", &x);
		T->pushEdge(x + 1, i);
	}
	
	bl = new BinaryLifting(T);
	bl->computeAncestry(1);

	for(int i = 1; i <= q; ++i) {
		int nod, up;
		fscanf(fin, "%d%d", &nod, &up);
		fprintf(fout, "%d\n", std::max(0, bl->goUp(nod + 1, up) - 1));
	}

	fclose(fin);
	fclose(fout);
	return 0;
}