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的主要内容,如果未能解决你的问题,请参考以下文章
Atcoder #017 agc017 D.Game on Tree 树上NIM 博弈