ABC202 E,Count Descendants(dfs+二分)

题意:

给出一棵树,然后让你求出树的第x层中有多少节点是y的子树?

思路:

首先我们肯定要统计出每个节点在第几层中.这个统计节点在第几层很容易想到用dfs或者bfs,但是我们建完树之后那.
然后就是如何记录那个节点是其他节点的子树?
我们可以用倍增的方法,但是如果一条链太长就行了,就会直接爆.然后用到一个新知识,get了时间戳.顾名思义就是单位时间,就是记录每一刻的时间.

首先我们为了方便叙述,用in[]数组表示进入这个点(子树)的时间,用out[]数组表示出去这个点(子树)的时间.
比如V是U的子树,那么我们就知道.\(in[u]<in[v]<out[v]<out[u]\).所以我们发现,in和out直接的所有范围内的时间都是该点的子树,这就把数据连续话,就让我们很好分析这个谁是谁的子树了,我们只需要比较时间即可,又因为,时间是连续的,所以我们就可以利用二分某一层的思想,来得到,该点在这一层有多少节点.

ll n,m,tim;
int in[maxn],out[maxn];
bool vis[maxn];/// biaoji 
vector<int> v[maxn],e[maxn];
void dfs(int x,int num){
	vis[x]=true;
	in[x]=++tim;
	e[num].push_back(in[x]);
	for(int i=0;i<(int)v[x].size();i++){
		ll y=v[x][i];
		if(vis[y]==false){
			dfs(y,num+1);
		}
	}	
	out[x]=++tim;
}
void solve()
{
	scanf("%lld",&n);
	for(int i=2;i<=n;i++){
		int x;
		scanf("%d",&x);		
		v[x].push_back(i);		
		v[i].push_back(x);
	}
	
	dfs(1,1);
	scanf("%lld",&m);
	while(m--){
		int x,y;
		scanf("%d%d",&x,&y);
		y++;
		int l=lower_bound(e[y].begin(),e[y].end(),in[x])-e[y].begin();
        int r=upper_bound(e[y].begin(),e[y].end(),out[x])-e[y].begin();
        printf("%d\n",r-l);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值