「Luogu1552」[APIO2012]派遣

「Luogu1552」[APIO2012]派遣

最近状态都不是很好,写完这个题感觉手感好像恢复了一些



problem

Solution

这个数据范围显然树形DP是做不了的

我们考虑,在预算范围内,选中的忍者越多越好,那么我们在一棵子树中选中的忍者一定是薪水最少的若干个

对每个节点维护一个大根堆,并记录每个堆的大小和堆中元素的权值和

考虑一棵子树时,用类似树形DP的方法将所有儿子合并到根

如果堆中元素权值和大于预算,不断弹出堆顶直到权值和不大于预算即可

最后对子树进行统计,更新答案

可并堆可以用左偏树实现

另外,还需要记录每个节点对应的左偏树的根的编号

Code

一开始没开long long还wa了一发

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;

template <typename T>void read(T &t)
{
    t=0;int f=0;char c=getchar();
    while(!isdigit(c)){f|=c=='-';c=getchar();}
    while(isdigit(c)){t=t*10+c-'0';c=getchar();}
    if(f)t=-t;
}

const int maxn=100000+5;
int n,root;
ll m;
ll mng[maxn];
ll ans;

struct edge
{
    int u,v,nxt;
}g[maxn];

int head[maxn],ecnt;
void eADD(int u,int v)
{
    g[++ecnt].u=u;
    g[ecnt].v=v;
    g[ecnt].nxt=head[u];
    head[u]=ecnt;
}

int rec[maxn];
struct node
{
    int ls,rs,dist;
    ll val,siz,sum;
}mxh[maxn];

int Merge(int x,int y)
{
    if(!x || !y)return x+y;
    if(mxh[x].val<mxh[y].val)swap(x,y);
    mxh[x].rs=Merge(mxh[x].rs,y);
    if(mxh[mxh[x].ls].dist<mxh[mxh[x].rs].dist)
        swap(mxh[x].ls,mxh[x].rs);
    mxh[x].dist=mxh[mxh[x].rs].dist+1;
    mxh[x].siz=mxh[mxh[x].ls].siz+mxh[mxh[x].rs].siz+1;
    mxh[x].sum=mxh[mxh[x].ls].sum+mxh[mxh[x].rs].sum+mxh[x].val;
    return x;
}

int Pop(int x)
{
    int ls=mxh[x].ls,rs=mxh[x].rs;
    return Merge(ls,rs);
}

void dfs(int u)
{
    for(register int i=head[u];i;i=g[i].nxt)
    {
        int v=g[i].v;
        dfs(v);
        rec[u]=Merge(rec[u],rec[v]);
    }
    while(mxh[rec[u]].sum>m && mxh[rec[u]].siz)
        rec[u]=Pop(rec[u]);
    ans=max(ans,1ll*mxh[rec[u]].siz*mng[u]);
}

int main()
{
    read(n),read(m);
    for(register int i=1;i<=n;++i)
    {
        int u;
        read(u),read(mxh[i].val),read(mng[i]);
        mxh[i].sum=mxh[i].val;
        mxh[i].siz=1;
        rec[i]=i;
        if(u)eADD(u,i);
        else root=i;
    }
    dfs(root);
    printf("%lld",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/lizbaka/p/10657928.html

时间: 2024-10-09 09:22:31

「Luogu1552」[APIO2012]派遣的相关文章

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

「随笔」基于当下的思考

马德,说好的技术blog,变成日记本了... 下午的时候莫名其妙的感到很颓废,因为自己的不够强大感到忧虑和危机感十足.现在每每行走在技术的道路上,常觉得如履薄冰,如芒在背. 上大学之前和现在的心态其实差别挺大的,视野的开阔远远不止局限于自己的脚下.不过,这里的「上大学之前」只是一个时间描述词,并不觉得大学是最适合学习的地方,我很失望. 世界上的人无论性别,区域,宗教,兴趣爱好,总可以在互联网上找到志趣相同的人,总是可以不断打破自己的常识与惯性思维.总是有在相同领域比自己更强的人,挺好的. 关于知

「Unity」与iOS、Android平台的整合:3、导出的Android-Studio工程

本文属于「Unity与iOS.Android平台的整合」系列文章之一,转载请注明出处. Unity默认导出的是Android-Eclipse工程,毕竟Eclipse for Android开发在近一两年才开始没落,用户量还是非常巨大的. 个人认为AndroidStudio非常好用,能轻易解决很多Eclipse解决不了或者很难解决的问题. 所以我将Unity导出的Andoid工程分为Eclipse和AndroidStudio两部分. 不过我之后的相关内容都会使用AndroidStudio,希望依然

大数据和「数据挖掘」是何关系?---来自知乎

知乎用户,互联网 244 人赞同 在我读数据挖掘方向研究生的时候:如果要描述数据量非常大,我们用Massive Data(海量数据)如果要描述数据非常多样,我们用Heterogeneous Data(异构数据)如果要描述数据既多样,又量大,我们用Massive Heterogeneous Data(海量异构数据)--如果要申请基金忽悠一笔钱,我们用Big Data(大数据) 编辑于 2014-02-2817 条评论感谢 收藏没有帮助举报作者保留权利 刘知远,NLPer 4 人赞同 我觉得 大数据

开放的智力8:实用「成功学」

可实现的「成功学」 现在我想为这里的年轻人介绍一种可实现的「成功学」.希望这个我自创的理论,可以改变很多人的一生. 当我们评价一个事情值不值得去做.应该花多少精力去做的时候,应该抛弃单一的视角,而是分两个不同的维度来看,一是该事件将给我带来的收益大小(认知.情感.物质.身体方面的收益皆可计入),即「收益值」:二是该收益随时间衰减的速度,我称为「收益半衰期」,半衰期长的事件,对我们的影响会持续得较久较长. 这两个维度正交以后就形成了一个四象限图.我们生活.学习和工作中的所有事情都可以放进这个图里面

Linux 小知识翻译 - 「syslog」

这次聊聊「syslog」. 上次聊了「日志」(lgo).这次说起syslog,一看到log(日志)就明白是怎么回事了.syslog是获取系统日志的工具. 很多UINIX系的OS都采用了这个程序,它承担了「获取系统全部的日志」这个维持系统正常运行的重要任务. syslog的本体是「syslogd」这个daemon(一般翻译成守护进程),常驻内存中获取日志. syslog的特点是可以通过配置文件「/etc/syslog.conf」,对「哪种应用程序?哪种重要度的信息?记录在哪个文件中?」等进行细致的

Linux 小知识翻译 - 「日志」(log)

这次聊聊「日志」. 「日志」主要指系统或者软件留下的「记录」.出自表示「航海日志」的「logbook」. 经常听说「出现问题的时候,或者程序没有安装自己预期的来运行的时候,请看看日志!」. 确实,记录了系统和软件详细运行情况的「日志」是信息的宝库,通过日志来解决问题的事例也非常多. 但事实上,「无论如何也不会看日志」的用户也有很多.理由很简单,日志的信息量非常大,全部用眼睛来看的话是非常吃力的. 而且,英语写的日志也会让英文不好的人敬而远之. 虽说「要养成用眼睛来看日志的习惯」,但实行起来却非常

Linux 小知识翻译 - 「补丁」(patch)

这次,聊聊补丁. 当有bug或者安全漏洞的时候,就会发布补丁.打上补丁之后,就能解决相应的bug或者安全漏洞. 那么,「补丁」到底是什么呢? 「补丁」只有少量的代码,一般都是对程序的一部分进行更新或者追加,包括bug修正,安全漏洞修正,功能追加或者变更等等.当然,只有「补丁」是无法运行的. 即,只有将「补丁」附加到原来的程序中,更新原来的程序后,才能运行. 「补丁(patch)」本来是指「打补丁用的小布头」.「patch」正是为了补足现有的程序,堵住程序漏洞的「布头」. 打「补丁」的时候需要用到

Linux 小知识翻译 - 「Linux」怎么读?

主要讨论日语中的读法,所以没有完全按照原文来翻译. 「linux」的读法有很多(这里指在日语中),代表性的读法有以下几种: A). 李纳苦思 B). 李奴苦思 C). 纳依纳苦思 A和B相同的是将 linux开头的「li」发音成「李」.这也是linux之父Linus Torvalds的名字的日语假名(「リーナス?トーバルズ」)的由来. linux中「nu」的发音是怎么样的呢?Linux Online的网页上有说明,而且视频中还有 Linus Torvalds 的发音. http://www.li