题目大意:给定 \(n\) 个数,每次可以任意选两个数 \(a_i,a_j\) 相加,把相加的结果作为一个新数继续执行此操作,直到只剩一个数为止。现要求使最后得出的这个数最小。

一个显然的贪心策略:每次选最小的两个数相加,得到一个新数,然后继续。但是,如果按照这样的思路,那么每次得到新数后这个序列的单调性就有可能会被破坏。

如何解决呢?很显然的一种方法,将新数加入序列后,再把这个序列排序。然而这样做似乎会超时。C++ STL 中提供了一种巧妙地解决方法:\(\mathtt{priority\_queue}\)。它地本质是建一个二叉堆,然后每当插入一个数,就维护这个二叉堆。那么显然,在这个题中,我们需要建一个小根堆,使较小的元素总是先被取出进行操作。

然后需要解决一个问题:

如何建立小根堆(使用\(\mathtt{priority\_queue}\))?

这样:priority_queue<int,vector<int>,greater<int> >q;。其中第一个 int 代表小根堆中存储的数据类型, vector<int> 代表存储的方式(vector 就是数组), greater<int> 就是从小到大(即小根堆)。然后大根堆的话就是 priority_queue<int,vector<int>,less<int> >q;

于是,做法就呼之欲出了:没读入一个数字,就插入小根堆中。然后,当元素个数大于等于 2 时循环,每次取出队首的两个元素相加,答案加上这个数字,再令新数入队即可。

请注意:这里为什么循环条件时元素个数大于等于 2而不是 队列不为空 呢?用兔队的一句话来回答:

参考代码:

#include <iostream>
#include <stdio.h>
#include <queue> using namespace std; int n,w;
priority_queue<int,vector<int>,greater<int> >q; int main()
{
long long ans=0;
scanf("%d",&n);
for(int i=1;i<=n;i++){scanf("%d",&w);q.push(w);}
while(q.size()>=2)
{
int x=q.top();q.pop();
int y=q.top();q.pop();
x+=y;
ans+=x;
q.push(x);
}
printf("%lld\n",ans);
return 0;
}

最新文章

  1. MySQL自增ID 起始值 修改方法
  2. UIImagePickerController 获取相片视频
  3. QT Creater + vs2010 发布程序
  4. ExtJs之Panel基本布局
  5. 第四讲 :hibernate中的session
  6. NUnit+mock+moq单元测试
  7. MVC使用Bootstrap
  8. mac下安装eclipse以及python
  9. css浮动--float/clear通俗讲解(转载)
  10. [活动] 【奖品撩人】部落守卫者集结令&#183;这一回同程SRC的安全由“我”守卫!
  11. [坑况]——windows升级node最新版本报错【npm install -g n】
  12. Linux下逻辑地址、线性地址、物理地址详细总结
  13. 优化网站设计(十):最小化JAVASCRIPT和CSS
  14. PCMU G.711U/PCMA G.711A简介
  15. Python 通过队列实现一个生产者消费者模型
  16. Spring AOP实现原理-动态代理
  17. Golang之并发篇
  18. js实现表单项的全选、反选以及删除操作
  19. PHP内核研究 静态变量
  20. jQuery插件 -- UI插件Tabs Widget 1.10

热门文章

  1. 小白的java学习之路 “ 字符串”
  2. Java连载76-基础数据类型包装类型及其方法简介
  3. 摇一摇—微信7.0.8版本audio无法自动播放问题
  4. css权重及计算
  5. php 公众号开发
  6. 将内裤穿在外面的男人(mysql)
  7. 针对wordpress CMS的信息收集
  8. 数据库SQL练习(一):数据查询
  9. MySql 存储大量长字节 Text报错处理办法
  10. Selenium3+python自动化007-Selenium常用定位方法