C. Colorful Tree 【树上启发式合并】

题目链接

 我这里的DP数组维护的是最少修改的次数

贪心的策略是每次先加所有子树个数,然后再减去子树所有颜色的个数最大值再+1;

发现这里需要有合并操作,所以时间复杂度满足nloglog的话,可以直接上set维护,好写

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+7;
#define debug(x) cout<<"! "<<x<<endl;
#define pb push_back
typedef long long ll;
ll col[N],dp[N];
vector<int>E[N];
multiset<int>s[N];
void dfs(int u){
	if(!E[u].size()){
		s[u].insert(col[u]);
		dp[u]=1;
		return;
	}
	int mx=1;
	for(auto v:E[u]){
		dfs(v);
		dp[u]+=dp[v];
		if(s[u].size()<s[v].size()) swap(s[u],s[v]);
		for(auto t:s[v]){
			s[u].insert(t);
			mx=max(mx,(int)s[u].count(t));
		}
	}
	multiset<int>ss;
	if(mx>1){
		for(auto v:s[u]){
			if(s[u].count(v)==mx&&!ss.count(v))
				ss.insert(v);
		}
		swap(s[u],ss);
	}
	dp[u]=dp[u]-mx+1;
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int n;cin>>n;
	for(int i=2;i<=n;i++){
		int x;cin>>x;
		E[x].pb(i);
	}
	for(int i=1;i<=n;i++) 
		cin>>col[i];
	dfs(1);
	// for(int i=1;i<=n;i++)
	// 	cout<<s[i].size()<<" ";
	// cout<<'\n';
	cout<<dp[1]<<'\n';
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值