51nod 1494 选举拉票【贪心】【扫描线】【线段树】2023华为od机试真题【人气最高的店铺】

51nod 1494 选举拉票和华为od机试真题【人气最高的店铺】,这两题的思路是一样的,所以放在一起分析.原题在最下面.

题解:

线段树的专题请自行了解,目的是为了性能,快速得到前K小的值.不在乎性能可以用优先队列,然后截取前K值求和即可.不影响我们的思路.至于扫描线,我也没有具现出来,所以不解析.

按题意.我们假设作为县长,首先获取所有选民的票数,总花费sum元,得到所有的选票n(包括投给自己和对手的票),然后逐步把选票还给原先对手.具体实现,先对对手的选票进行代价从高到低排序,如示例中:1 2,1 2,1 2,2 1,0 0.解析求得1号对手有[2,2,2],2号对手有[1],自己不算.我们再分为代价rank组,rank[1]=[2,1],rank[2] =[2],rank[3]=[2].这里的含义就是当我们把rank[1]的票退回给对手,这时对手(1,2)手上至多有1票,这时只要我们县长手上的票比1大,则成立我们具有最多的票.再把rank[2]退回,那么对手(1)手上至多有2票,而我们这时如果不够3票,那么就要从退回的票中选择差值个k票,取前k小代价的.如此类推,当我们把rank都退回,示例中,我们只有1票,而对手有3票,所以我们从选票中选取  3-1+1 =3(k)票,加1是为了比3大.枚举所有对手可能拥有的票,而不是我们所有的票,只要比对手多一票即可.

核心代码

     // n是总票数,ans是已统计出的所以选择的代码总和
      let c = n, sum = ans;
     // i的循环次数,是对手最大的选票次数.所以这里可以优化,只要循环rank的范围即可
     for (let i = 1; i <= n; i++) {
        // 表示手上的票
        c -= b[i].length;
        // 
  • 68
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值