Codeforces 246E Blood Cousins Return
数据结构,dsu on tree
题意
一棵树,每一个点有一个颜色(字符串),每一次询问以某一个点为根的子树中与其距离为k的点有多少种颜色。
思路
dsu on tree。因为第二次dfs时每个深度的信息都要记录,就对每一个深度开一个set,记录这个深度下出现过的颜色即可。
dfs完一个节点,将它的深度加上询问的深度,就是实际深度,查询这个深度的set的size即可。
注意不是树,是森林,记一下所有的root即可。
代码
#include<bits\stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int MAXN=100007;
typedef long long LL;
struct Edge
{
int to, ne;
}e[MAXN<<1];
int head[MAXN], edgenum;
int val[MAXN];
struct Query
{
int k, ne;int id;
}qn[MAXN];
int qhead[MAXN], qam;
int sz[MAXN], hson[MAXN], dp[MAXN];
map<string, int> ha;
void findson(int u, int fa)
{
sz[u]=1;
if(fa==-1) dp[u]=1;
else dp[u]=dp[fa]+1;
for(int i=head[u];~i;i=e[i].ne)
{
int to=e[i].to;
if(to!=fa)
{
findson(to, u);
if(!hson) hson[u]=to;
else if(sz[hson[u]]<sz[to]) hson[u]=to;
sz[u]+=sz[to];
}
}
}
int hs;set<int> cnt[MAXN];
void suan(int u, int fa, int v)
{
if(v==1)
cnt[dp[u]].insert(val[u]);
else cnt[dp[u]].erase(val[u]);
for(int i=head[u];~i;i=e[i].ne)
if(e[i].to!=fa&&e[i].to!=hs)
suan(e[i].to, u, v);
}
int res[MAXN];
void dfs(int u, int fa, int kp)
{
for(int i=head[u];~i;i=e[i].ne)
{
int to=e[i].to;
if(to!=fa&&to!=hson[u])
dfs(to, u, 0);
}
if(hson[u]) dfs(hson[u], u, 1), hs=hson[u];
suan(u, fa, 1);hs=0;
for(int i=qhead[u];~i;i=qn[i].ne)
{
int hi=dp[u]+qn[i].k;
if(hi>=MAXN) res[qn[i].id]=0;
else res[qn[i].id]=cnt[hi].size();
}
if(!kp) suan(u, fa, -1);
}
vector<int> roots;
int main()
{
int n;
while(scanf("%d", &n)==1)
{
M(head, -1), M(qhead, -1);edgenum=qam=0;
roots.clear();
int colam=0;
for(int i=1;i<=n;i++)
{
string tmps;cin>>tmps;
if(!ha[tmps]) ha[tmps]=++colam, val[i]=colam;
else val[i]=ha[tmps];
int p=i, q;scanf("%d", &q);
if(q==0)
{
roots.push_back(i);
continue;
}
e[edgenum].to=q, e[edgenum].ne=head[p], head[p]=edgenum++;
e[edgenum].to=p, e[edgenum].ne=head[q], head[q]=edgenum++;
}
int q;scanf("%d", &q);
for(int i=1;i<=q;i++)
{
int t1, t2;scanf("%d%d", &t1, &t2);
qn[qam].k=t2, qn[qam].ne=qhead[t1], qn[qam].id=i, qhead[t1]=qam++;
}
for(int i : roots)
findson(i, -1);
for(int i:roots)
dfs(i, -1, 0);
for(int i=1;i<=q;i++)
printf("%d\n", res[i]);
}
//system("pause");
return 0;
}