问题描述
何老板的公司有n名员工,编号1到n。除了何老板以外,每个员工都有且仅有一名直接上司。每个员工可能有0个或多个直接下属。
公司采取等级制度,等级越大的员工工资越低。何老板的工资最高,他的等级为1。每个员工的等级数都比他的直接上司的等级数大1。
何老板向你提问,i号员工管辖的部门中,等级为k的有多少个人(包括i本人)?
i号员工管辖的部门包括i和i所有的直接或间接下属。
何老板向你提了m次问题,你要快速回答出所有的提问。
输入格式
第一行,两个整数n和m 接下来n-1行,每行两个整数,x和y,表示x是y的直接上司。 接下来m行,每行一个整数i和k,表示一次提问。
输出格式
m行,对于每个提问,输出一行,一个整数,表示问题答案。
样例输入
12 3
3 1
3 2
3 4
1 8
1 5
1 7
2 6
4 9
6 11
6 12
5 10
1 3
2 4
4 4
样例输出
3
2
0
题解
dfs序,如果一节点的in值介于一节点的in与out值之间那么说明此节点为该节点的儿子。
因此,开一个动态数组记录每个深度的in值,因为是依次增加的,所以该数组具有递增性所以对于询问只需要二分查找in值介于该上司的in与out值间的的节点数即可
注意stl的使用!
vector::iterator t1,t2;
代码
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define maxn 100005
int n,m;
int Next[maxn],End[maxn],Last[maxn];
int cnt;
int vis;
int dep[maxn];
int in[maxn],ou[maxn];
int f[maxn],ru[maxn];
vector<int>q[maxn];
vector<int>::iterator t1,t2;
void dfs(int x)
{
int i,j,k;
dep[x]=dep[f[x]]+1;
in[x]=++vis;
q[dep[x]].push_back(vis);
for(i=Last[x];i;i=Next[i]){
int en=End[i];
f[en]=x;
dfs(en);
}
ou[x]=vis;
}
void insert(int x,int y)
{
Next[++cnt]=Last[x];
Last[x]=cnt;
End[cnt]=y;
}
int main()
{
int i,j;
scanf("%d%d",&n,&m);
for(i=1;i<=n-1;i++){
int x,y;
scanf("%d%d",&x,&y);
insert(x,y);
ru[y]++;
}
for(i=1;i<=n;i++) if(!ru[i]) dfs(i);
for(i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
int x1=in[x],y1=ou[x];
t1=lower_bound(q[y].begin(),q[y].end(),x1);
t2=upper_bound(q[y].begin(),q[y].end(),y1);
cout<<t2-t1<<endl;
}
}