题解:P12479 [集训队互测 2024] 长野原龙势流星群

题目:

唉不是,这个 trick 我见过啊 QAQ!

我们想一下特殊点,发现最大的点肯定选自己,然后又会发现他的父亲也必选他,所以每次找最大的点和他父亲合并成新点即可。

合并了贪心选点的过程。

#include<bits/stdc++.h>
using namespace std;
const int QAQ=2e5+7;
#define db double
int n,f[QAQ],fa[QAQ];
vector<int> dian[QAQ];
#define int long long

struct xxx {int sum,cnt,x;};

bool operator <(xxx a,xxx b)
{
	if(a.sum*b.cnt==b.sum*a.cnt) return a.x<b.x;
	return a.sum*b.cnt<b.sum*a.cnt;
}

set<xxx> dui;
bool vis[QAQ];
int cnt[QAQ];
double ans[QAQ],w[QAQ];
int find(int x) {return x==f[x]?x:find(f[x]);}
signed main()
{
	cin>>n;
	f[1]=1,cnt[1]=1;
	for(int i=2;i<=n;i++) cin>>fa[i],f[i]=i,cnt[i]=1;
	for(int i=1;i<=n;i++) cin>>w[i],dui.insert({w[i],cnt[i],i});
	while(!dui.empty())
	{
		xxx nw=(*--dui.end());
		dui.erase(nw);
		if(nw.x==0) continue;
		ans[nw.x]=(db)nw.sum/nw.cnt;
		vis[nw.x]=1;
		int v=find(fa[nw.x]);
		
		
		dui.erase({w[v],cnt[v],v});
		
		cnt[v]+=cnt[nw.x];
		w[v]+=w[nw.x];
		f[nw.x]=v;
		dui.insert({w[v],cnt[v],v});
	}
	for(int i=1;i<=n;i++) printf("%.7f\n",ans[i]);
	return 0;
}
posted @ 2025-09-27 11:53  _a1a2a3a4a5  阅读(11)  评论(0)    收藏  举报