LibreOJ #2509.「HNOI2018」排列 贪心+堆

51人阅读 评论(0) 收藏 举报
分类:

题意

这里写图片描述
n<=500000

分析

不难分析到其实就是有一棵树,然后每次要选一个节点。在选某个节点时必须先选其父节点,第i个选的节点的系数为i,问最大的权值和。
先这么想,对于一个最权值小的节点,当我们选了其父亲后,必然会马上选它。那么我们就可以把它和它父亲并在一起。
那合并后的新权值是什么呢?设w表示其权值和,s表示其元素个数,那么新权值就是w/s。
为什么可以这么定权值呢?考虑比较两个集合S1和S2,若S1放前面较优,则有w2s2>w1s2
那么这么做就很显然了。
用堆来维护即可。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define mp(x,y) std::make_pair(x,y)

typedef long long LL;
typedef std::pair<long double,int> pi;

const int N=500005;
const int inf=2000000000;

int n,fa[N],f[N],s[N];
LL w[N];

struct Queue
{
    std::priority_queue<pi> a,b;

    void push(pi x)
    {
        a.push(x);
    }

    void pop()
    {
        while (!b.empty()&&a.top()==b.top()) a.pop(),b.pop();
        a.pop();
    }

    void erase(pi x)
    {
        b.push(x);
    }

    pi top()
    {
        while (!b.empty()&&a.top()==b.top()) a.pop(),b.pop();
        return a.top();
    }
}que;

int find(int x)
{
    if (f[x]==x) return x;
    else return f[x]=find(f[x]);
}

int main()
{
    scanf("%d",&n);
    for (int i=0;i<=n;i++) f[i]=i;
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&fa[i]);
        if (f[find(i)]==f[find(fa[i])]) {puts("-1");return 0;}
        f[find(i)]=find(fa[i]);
    }
    LL ans=0;
    f[0]=0;
    for (int i=1;i<=n;i++) scanf("%lld",&w[i]),ans+=w[i];
    for (int i=1;i<=n;i++) f[i]=i,s[i]=1,que.push(mp(-(long double)w[i],i));
    for (int i=1;i<=n;i++)
    {
        int x=que.top().second,y=find(fa[x]);que.pop();
        if (y) que.erase(mp(-(long double)w[y]/s[y],y));
        ans+=(LL)s[y]*w[x];
        w[y]+=w[x];s[y]+=s[x];f[x]=y;
        if (y) que.push(mp(-(long double)w[y]/s[y],y));
    }
    printf("%lld",ans);
    return 0;
}
查看评论

HNOI2018 总结

听说可以报名HNOI玩一玩,就去玩了一玩Day0HNOI的流程比较简单,也没有什么报道,就是两天早上考试,下午出成绩,好像讲题都没有。 所以Day0就以找晚餐为由出去走了几个小时Day1由于酒店里考...
  • u011056504
  • u011056504
  • 2018-04-16 11:00:14
  • 259

HNOI2018翻水记

day0 又一次来到了长沙南站。 毕竟不是自己省选所以感觉比较轻松,晚上爽快战斗一下就睡觉了。 day1 看完题后发现好像三题都不是很可做,于是就选择先去刚看起来最清真的t1。 搞来搞去...
  • qq_33229466
  • qq_33229466
  • 2018-04-15 18:50:49
  • 166

LibreOJ #2510.「HNOI2018」道路 树形dp

题意 分析 在考场上的时候以为这是神仙题,就没有太仔细想,结果这就是一道普及dp题。 设f[d,x,y]表示以d为根的子树,上面有x条公路,y条铁路时的最优翻修方案。 记忆化搜索一...
  • qq_33229466
  • qq_33229466
  • 2018-04-16 19:22:47
  • 52

loj 2508. 「AHOI / HNOI2018」游戏

题意: 题解: 显然每个点能到达的范围是一段区间,假如能预处理出来,询问就很好办了。 首先将没有们的点缩在一起,考虑i-&amp;gt;i+1这一道门,假如钥匙在i前面,那么i+1就一定...
  • qq_36808030
  • qq_36808030
  • 2018-04-19 15:37:30
  • 45

loj 2509. 「AHOI / HNOI2018」排列

题意: 题解: 感觉很难啊,听说考场乱搞能拿70…… 容易转化题意为在森林上移除根节点,每次获得的分数是权值乘上操作次数。 然后就想了各种 随手卡的 sb贪心。 正解挺好的,思路上是...
  • qq_36808030
  • qq_36808030
  • 2018-04-18 15:07:53
  • 14

[bzoj5289][Hnoi2018]排列【贪心】【堆】

【题目链接】   https://www.lydsy.com/JudgeOnline/problem.php?id=5289   https://www.luogu.org/problemnew/...
  • D_Vanisher
  • D_Vanisher
  • 2018-04-19 21:37:27
  • 20

#515. 「LibreOJ β Round #2」贪心只能过样例 (简单dp+bitset优化)

题目描述 一共有 nnn个数,第 iii 个数 xix_ix​i​​ 可以取 [ai,bi][a_i , b_i][a​i​​,b​i​​] 中任意值。 设 S=∑xi2S = \...
  • qq_34374664
  • qq_34374664
  • 2017-07-07 00:58:19
  • 406

#515. 「LibreOJ β Round #2」贪心只能过样例 背包+bitset优化

pdf 题意: 一共有 nnn个数,第 iii 个数 xix_ix​i​​ 可以取 [ai,bi][a_i , b_i][a​i​​,b​i​​] 中任意值...
  • HowardEmily
  • HowardEmily
  • 2017-07-17 16:32:50
  • 252

「LibreOJ β Round #2」贪心只能过样例 [bitset]【STL】

题目链接:https://loj.ac/problem/515 ——————————————————————————————————515. 「LibreOJ β Round #2」贪心只能过样例内...
  • qq_33184171
  • qq_33184171
  • 2017-07-03 14:51:58
  • 470
    个人资料
    持之以恒
    等级:
    访问量: 26万+
    积分: 1万+
    排名: 1482
    文章分类
    最新评论