题解:set+dsu on the tree
STL大法好!对于每个深度开一个set记录每种颜色的信息。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#define N 200003
using namespace std;
int n,m,size[N],son[N],mark[N],deep[N],tot,col[N];
int ans[N],point[N],head[N],v[N],nxt[N],next[N],u[N],num[N];
map<string,int> mp;
set<int> dep[N];
void add(int x,int y){
tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void build(int x,int y,int z){
tot++; next[tot]=head[x]; head[x]=tot; u[tot]=y; num[tot]=z;
}
void solve(int x,int fa)
{
size[x]=1; deep[x]=deep[fa]+1;
for (int i=point[x];i;i=nxt[i]){
if (v[i]==fa) continue;
solve(v[i],x);
size[x]+=size[v[i]];
if (size[son[x]]<size[v[i]]) son[x]=v[i];
}
}
void calc(int x,int fa)
{
dep[deep[x]].insert(col[x]);
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa&&!mark[v[i]]) calc(v[i],x);
}
void clear(int x,int fa)
{
dep[deep[x]].clear();
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa&&!mark[v[i]]) clear(v[i],x);
}
void dfs(int x,int fa,bool k)
{
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa&&v[i]!=son[x]) dfs(v[i],x,0);
if (son[x]) dfs(son[x],x,1),mark[son[x]]=1;
calc(x,fa);
for (int i=head[x];i;i=next[i]) {
int t;
if((t=deep[x]+u[i])>100001) continue;
ans[num[i]]=dep[t].size();
}
if (son[x]) mark[son[x]]=0;
if (!k) clear(x,fa);
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&n);
string s; int root=0; int cnt=0;
for (int i=1;i<=n;i++) {
cin>>s; int x; scanf("%d",&x);
add(x,i);
if (!mp[s]) mp[s]=++cnt;
col[i]=mp[s];
}
//for (int i=1;i<=n;i++) cout<<col[i]<<" ";
//cout<<endl;
scanf("%d",&m); tot=0;
for (int i=1;i<=m;i++) {
int x,y; scanf("%d%d",&x,&y);
build(x,y,i);
}
solve(root,0);
dfs(root,0,0);
for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
}