E. Blood Cousins Return(dsu+set)

其实也差不多是dsu的模板题了

开个二维数组记录当前子树每个深度各种名字出现的情况

但是空间不够

使 , s e t 所以使用一维数组,每个元素都是一个set来记录名字出现的哈希值

这样就是模板题目了

#include <bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
struct edge{
	int u,to,nxt,ans;
}d[maxn],ask[maxn]; int head[maxn],cnt=1,head1[maxn],cnt1=1;
void add(int u,int v){
	d[++cnt]=(edge){u,v,head[u],0},head[u]=cnt;
}
void ins(int u,int v){
	ask[++cnt1]=(edge){u,v,head1[u],0},head1[u]=cnt1;
}
map<string,int>mp;
int id,son[maxn],siz[maxn],deep[maxn],has[maxn];
string a[maxn];
void dfs(int u,int father,int depth)
{
	siz[u]=1,deep[u]=depth;
	int maxson=-1;
	for(int i=head[u];i;i=d[i].nxt )
	{
		int v=d[i].to;
		if( v==father )	continue;
		dfs(v,u,depth+1);
		siz[u]+=siz[v];
		if( maxson<siz[v] )	maxson=siz[v],son[u]=v;
	}
}
int nowson;
set<int>s[maxn];
void update(int u,int father,int val)
{
	if( val==1 )	s[deep[u]].insert(has[u]);
	else	s[ deep[u] ].erase( has[u] );
	for(int i=head[u];i;i=d[i].nxt )
	{
		if( d[i].to!=father&&d[i].to!=nowson )
			update(d[i].to,u,val);
	}
}
void dsu(int u,int father,bool keep)
{
	for(int i=head[u];i;i=d[i].nxt )
	{
		int v=d[i].to;
		if( v==father || v==son[u] )	continue;
		dsu(v,u,0);
	}
	if( son[u] )	dsu(son[u],u,1),nowson=son[u];
	update(u,father,1); nowson=0;
	for(int i=head1[u];i;i=ask[i].nxt )
	{
		int v=ask[i].u;
		ask[i].ans=s[deep[u]+ask[i].to].size();
	}
	/*处理答案
	*/
	if( !keep )	update(u,father,-1);
}
int main()
{
	int root=0;
	int n,m;
	cin >> n;
	for(int i=1;i<=n;i++)
	{
		int x; cin >> a[i] >> x;
		if( !mp[a[i]] )	mp[a[i]]=++id;
		has[i]=mp[a[i]];
		if( x==0 )	add(root,i),add(i,root);
		else	add(i,x),add(x,i);
	}
	dfs(root,0,1);
	cin >> m;
	for(int i=1;i<=m;i++)
	{
		int l,r;	cin >> l >> r;
		ins(l,r);
	}
	dsu(root,0,1);
	for(int i=2;i<=m+1;i++)
		cout << ask[i].ans << '\n';
}

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/108337543