agc023F - 01 on Tree

Posted gmh77

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了agc023F - 01 on Tree相关的知识,希望对你有一定的参考价值。

题目描述

技术图片

题解

经典魔塔模型(

设(ai,bi)表示一个块的0/1个数,块i在块j前满足biaj<bjai,化一下变成ai/bi>aj/bj

如果没有树的限制就直接选,否则如果有一个劣的节点在上面,优的节点在下面,则选完劣的后必须要选优的,可以把优的和其父亲合并,注意相同时要先合并上面的

用堆从大到小搞,合并完之后的树满足其儿子一定更劣,所以贪心选即可

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

struct type{ll a,b;int id;} c[200001],s;
int Fa[200001],fa[200001],b[200001],n,i,j,k,l;
bool bz[200001];
ll ans,sum;

bool operator < (type a,type b) {return !(a.b*b.a<b.b*a.a || a.b*b.a==b.b*a.a && a.id<b.id);}
bool cmp(type a,type b) {return a.b*b.a<b.b*a.a;}
priority_queue<type> hp;

int gf(int t) {if (fa[t]==t) return t; fa[t]=gf(fa[t]);return fa[t];}

int main()
{
	#ifdef file
	freopen("agc023F.in","r",stdin);
//	freopen("b.out","w",stdout);
	#endif
	
	scanf("%d",&n);
	fo(i,2,n) scanf("%d",&Fa[i]);
	fo(i,1,n) scanf("%d",&b[i]),sum+=!b[i],c[i].a=b[i]==0,c[i].b=b[i]==1,c[i].id=i,fa[i]=i;
	fd(i,n,1)
	if (!b[i]) c[Fa[i]].a+=c[i].a,fa[i]=Fa[i],bz[i]=1; else hp.push(c[i]),ans+=c[i].a;
	sum-=c[0].a;
	
	while (!hp.empty())
	{
		s=hp.top(),hp.pop();
		if (c[s.id].b!=s.b) continue;
		
		j=gf(Fa[gf(s.id)]);
		if (j && cmp(s,c[j]))
		{
			ans+=c[j].b*s.a;
			c[j].a+=s.a,c[j].b+=s.b;
			fa[s.id]=j,hp.push(c[j]);
			bz[s.id]=1;
		}
	}
	fo(i,1,n) if (!bz[i]) hp.push(c[i]),j=gf(Fa[j]);
	while (!hp.empty())
	{
		s=hp.top(),hp.pop();
		sum-=s.a,ans+=s.b*sum;
	}
	printf("%lld
",ans);
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}

以上是关于agc023F - 01 on Tree的主要内容,如果未能解决你的问题,请参考以下文章

AGC017D Game on Tree(树型博弈)

Atcoder #017 agc017 D.Game on Tree 树上NIM 博弈

AtCoder AGC030B Tree Burning

AGC 030 B - Tree Burning

AGC 030 B - Tree Burning 结论+枚举

[AGC058C]Planar Tree