Dfs搜索树(Codeforces 1006E)

算是很水很裸的一道  dfs树上搜索

原本是想记录 每个点的 子节点 所包含的 点集分支内 有多少个点

如果结果在这个范围内,就搜索这个树枝,这样就是一条线路 的查询 平均查询复杂度为 O(log(n))

然后完整复杂度为 n*logn ,估计数据出了那种一条直线的树,就T了,改用下面的方法就过了。

 

先根遍历的节点记录

Dfs搜索树(Codeforces 1006E)_第1张图片

每个点都有它的子节点

  1. 记录每个点(算上这个点) 的子图 内点个数
  2. 记录每个点从  1号点  开始搜索的次序 (eg:第四个搜索到的点 -> 对应 5)
  3. 记录一个点 在搜索时的 序号(eg: 6 是 第五个搜索到的点)

然后 判断完这个点所包含的点集是不是有k个点 ,如果有直接O(1)查询就完事了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define Clear( x , y ) memset( x , y , sizeof(x) );
#define Qcin() std::ios::sync_with_stdio(false);
using namespace std;
typedef long long LL;
const int Maxn = 2 * 1e5 + 7;
const int Inf = 1e9 + 7;
int N , q , k;
vector  G[Maxn];
int vis[Maxn] , cnt[Maxn] , F[Maxn];
int Dfs(int x , int num){
	vis[x]++;
	cnt[x] = num + 1;
	F[++num] = x;
	for(int i = 0 ; i < G[x].size() ; i++){
		vis[x] += Dfs(G[x][i] , num);
		num += vis[G[x][i]];
	}
	return vis[x];
}
int main()
{
	int x;
	scanf(" %d %d",&N , &q);
	for(int i = 2 ; i <= N ; i++){
		scanf(" %d",&x);
		G[x].push_back(i);
	}
	x = Dfs(1 , 0);
	/*
	for(int i = 1 ; i <= N ; i++){
		printf("#%d = %d %d\n",i , cnt[i] , F[i]);
	}
	*/
	while(q--){
		scanf(" %d %d",&x , &k);
		if(vis[x] < k){
			printf("-1\n");
			continue;
		}
		printf("%d\n",F[cnt[x]+k-1]);
	}
	return 0;
}

 

你可能感兴趣的:(acm散篇填充)