您的位置:首页 > 其它

BZOJ 2809 [Apio2012]dispatching

2017-01-20 23:34 337 查看
可并堆

如果固定了管理者,那一定是贪心地选取子树内最小的若干个。因此用大根堆维护子树值,满足总和小于m,然后合并给父亲。

#include<cstdio>
#include<algorithm>
#define N 100005
#define ll long long
using namespace std;
namespace runzhe2000
{
int n, m, fa
, mon
, abi
, root
;
ll ans;

struct heap // big root
{
int ch[2]; ll v; int dis; ll sum; int cnt;
}h
;
int merge(int x, int y)
{
if(!x)return y; if(!y)return x;
if(h[x].v < h[y].v) swap(x, y);
h[x].ch[1] = merge(h[x].ch[1], y);
if(h[h[x].ch[0]].dis < h[h[x].ch[1]].dis) swap(h[x].ch[0], h[x].ch[1]);
h[x].dis = h[h[x].ch[1]].dis + 1;
h[x].sum = h[x].v + h[h[x].ch[0]].sum + h[h[x].ch[1]].sum;
h[x].cnt = 1 + h[h[x].ch[0]].cnt + h[h[x].ch[1]].cnt;
return x;
}
int pop(int x){return merge(h[x].ch[0], h[x].ch[1]);}

void main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
{
scanf("%d%d%d",&fa[i],&mon[i],&abi[i]);
root[i] = i;
h[i] = (heap){{0,0},mon[i],0,mon[i],1};
}
for(int i = n; i; i--)
{
while(h[root[i]].sum > m) root[i] = pop(root[i]);
ll tmp = (ll)h[root[i]].cnt * abi[i];
ans = max(ans, tmp);
root[fa[i]] = merge(root[fa[i]], root[i]) ;
}
printf("%lld\n",ans);
}
}
int main()
{
runzhe2000::main();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: