题目

链接:https://ac.nowcoder.com/acm/contest/26887/1001
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

​ 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。

​ 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。

​ 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。

例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。

输入描述:

输入包括两行,第一行是一个整数n(1<=n<=10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1<=ai<=20000)是第i种果子的数目。

输出描述:

输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于231。

示例1

输入

3
1 2 9

输出

15

备注:

对于30%的数据,保证有n<=1000:
对于50%的数据,保证有n<=5000;
对于全部的数据,保证有n<=10000。

题解

1.贪心

每一次合并最小的两堆果子

2.实现方法

1)使用两个单调栈(O(n))

2)使用二叉堆(优先队列) (O(log2 N))

一.使用STL//注意:默认是大根堆,有两种解决办法:一种是使用相反数,第二种是利用语法规则改变排序的使用

转载自:https://blog.csdn.net/S_999999/article/details/88555829

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct cmp{ bool operator () ( int r , int l ){
return r > l;
}
};
struct cmp1{
bool operator ()( int a ,int b ){
return a<b;
}
};
int main(void){ // priority_queue< int > q;// 默认是 从大到小。
// priority_queue < int , vector<int> ,less<int> > q;//从大到小
// priority_queue < int , vector<int>, greater<int> > q; //从小到大,需要vector
// priority_queue < int , vector<int> , cmp1 > q;//从大到小,需要vector
// priority_queue < int , vector<int> , cmp > q;//从小到大,需要vector
q.push( 1 );
q.push( 2 );
q.push( 3 ); while( !q.empty() ){
int t =q.top();
q.pop();
printf("%d ",t); }
return 0;
}
//有没有发现重载操作符的时候比sort更加少

二.自己设计一颗树(注意:比赛可以使用STL)

在这里的误区:在制造容器的时候进行了一次复制,但是没有及时更正不一样的地方

#include <iostream>
#include <algorithm>
#include <utility>
#include <string_view>
using namespace std;
int q[10010];//这里写的是小根堆,最上面是q[1]
int cnt = 0;
inline void mswap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
inline void pop()
{
q[1] = q[cnt];
cnt--;
int m = 1;
int n = m * 2;//注意底下要在两个儿子之间做出选择
if (n + 1 <= cnt && q[n + 1] < q[n])
n++;
while (n <= cnt && q[m] > q[n])
{
mswap(q[m], q[n]);
m = n;
n = m * 2;//注意底下要在两个儿子之间做出选择
if (n + 1 <= cnt && q[n + 1] < q[n])
n++; }
}
inline void push(int x)
{
cnt++;
q[cnt] = x;
int m = cnt;
int n = cnt / 2;
while (n && q[m] < q[n])
{
mswap(q[n], q[m]);
m = n;
n = n / 2;
}
}
inline int top()
{
return q[1];
}

代码

代码一(使用自己写的二叉堆)

#include <iostream>
#include <algorithm>
#include <utility>
#include <string_view>
using namespace std;
int q[10010];//这里写的是小根堆,最上面是q[1]
int cnt = 0;
inline void mswap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
inline void pop()
{
q[1] = q[cnt];
cnt--;
int m = 1;
int n = m * 2;//注意底下要在两个儿子之间做出选择
if (n + 1 <= cnt && q[n + 1] < q[n])
n++;
while (n <= cnt && q[m] > q[n])
{
mswap(q[m], q[n]);
m = n;
n = m * 2;//注意底下要在两个儿子之间做出选择
if (n + 1 <= cnt && q[n + 1] < q[n])
n++; }
}
inline void push(int x)
{
cnt++;
q[cnt] = x;
int m = cnt;
int n = cnt / 2;
while (n && q[m] < q[n])
{
mswap(q[n], q[m]);
m = n;
n = n / 2;
}
}
inline int top()
{
return q[1];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int ans = 0;
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
int tmp;
cin >> tmp;
push(tmp);
}
for (int i = 0; i < n - 1; i++)
{
int t1, t2;
t1 = top();
pop();
t2 = top();
pop();
ans += t1 + t2;
push(t1 + t2); }
cout << ans;
return 0;
}

代码二(使用STL容器)注意我这里是最伟大的自定义函数

#include <iostream>
#include <queue>
#include <vector> using namespace std;
struct cmp
{
bool operator()(int x, int y)
{
return x > y;
}
};
priority_queue<int, vector<int>, cmp >q;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int ans = 0;
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
int tmp;
cin >> tmp;
q.push(tmp);
}
for (int i = 0; i < n - 1; i++)
{
int t1, t2;
t1 = q.top();
q.pop();
t2 = q.top();
q.pop();
ans += t1 + t2;
q.push(t1 + t2); }
cout << ans;
return 0;
}

代码三(使用了单调栈)[最快的代码!!!]

参考:https://www.luogu.com.cn/blog/171554/solution-p6038

基本思想:没有必要把所有的数据按顺序都放到一起,按照顺序放到两处也不是不可以!!!

顺便再带一个桶排序,更快!!

#include <iostream>
#include <queue>
#define MAX 10010
using namespace std;
queue<int>q1;
queue<int>q2;
int to[MAX];
int main()
{
int ans = 0;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int tmp;
cin >> tmp;
to[tmp] ++;
}//进行桶排序
for (int i = 0; i < MAX; i++)
{
while (to[i])
{
to[i]--;
q1.push(i);
}
}
for (int i = 0; i < n - 1; i++)
{
int a, b;
if (q1.empty() || !q2.empty() && q2.front() < q1.front())
{
a = q2.front();
q2.pop();
}
else
{
a = q1.front();
q1.pop();
}
if (q1.empty() || !q2.empty() && q2.front() < q1.front())
{
b = q2.front();
q2.pop();
}
else
{
b = q1.front();
q1.pop();
}
ans += a + b;
q2.push(a + b);
}
cout << ans;
return 0;
}

加强版:合并果子[NOIP2004]的更多相关文章

  1. 合并果子(NOIP2004)

    合并果子(NOIP2004)[问题描述]在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆.每一次合并,多多可以把两堆果子合并到一起,消耗的体 ...

  2. NC16663 [NOIP2004]合并果子

    NC16663 [NOIP2004]合并果子 题目 题目描述 ​ 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. ​ 每一次合并,多多可 ...

  3. NOIP2004合并果子

    题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...

  4. [luoguP1090][Noip2004]合并果子

                                            合并果子 首先来看一下题目: (OI2004合并果子) [题目描述] 果园里,多多已经将所有的果子打了下来,而且按果子的 ...

  5. [Noip2004][Day ?][T?]合并果子(?.cpp)

    题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...

  6. [NOIP2004] 提高组 洛谷P1090 合并果子

    题目描述 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和.可 ...

  7. 代码源 每日一题 分割 洛谷 P6033合并果子

    ​ 题目链接:切割 - 题目 - Daimayuan Online Judge 数据加强版链接: [NOIP2004 提高组] 合并果子 加强版 - 洛谷 题目描述 有一个长度为 ∑ai 的木板,需要 ...

  8. 合并果子 (codevs 1063) 题解

    [问题描述] 在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆.多多决定把所有的果子合成一堆. 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和 ...

  9. JZOJ 1775. 合并果子2 (Standard IO)

    1775. 合并果子2 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Description 在一个果园里,多多已经将所有的果子 ...

随机推荐

  1. 2022管家婆工贸版ERP T3 V22.0工厂管理软件单机网络版无限用户免狗软件可定制

    管家婆工贸版是一款针对国内中小加工企业开发的管理软件,软件以财务管理为核心,集采购.销售.存货.生产.工资.固定资产.账务管理等模块于一体,对企业的信息进行监控,实现对企业物流.资金流.信息流和生产成 ...

  2. 832. Flipping an Image - LeetCode

    Question 832. Flipping an Image Solution 题目大意:将1列与最后n列对换,2列与n-1列对换-然后再将每个元素取反 思路:遍历二维数组的左半边,对每个元素先做对 ...

  3. 印尼医疗龙头企业Halodoc的数据平台转型之Lakehouse架构

    1. 摘要 在 Halodoc,我们始终致力于为最终用户简化医疗保健服务,随着公司的发展,我们不断构建和提供新功能. 我们两年前建立的可能无法支持我们今天管理的数据量,以解决我们决定改进数据平台架构的 ...

  4. mysql外键与表查询

    目录 自增特性 外键 外键关系 外键创建 外键的约束效果 级联更新级联删除 多对多关系 一对一关系 表查询关键字 select与from where筛选 group by分组 练习 关系练习 查询练习 ...

  5. 选择器补充与CSS属性

    目录 伪元素选择器 选择器优先级 CSS属性 宽和高 字体样式 文字属性 背景属性 边框属性 display属性 盒子模型 浮动(float) 清除浮动 伪元素选择器 伪元素选择器可以通过CSS操作文 ...

  6. bind-utils-测试域名解析

    bind-utils是一个网络管理类工具集,其集成了我们常用的命令"nslookup",我们可以使用诊断域名解析情况. 1.安装bind-utils [root@localhost ...

  7. 【Java面试】如何中断一个正在运行的线程?

    一个去京东面试的工作了5年的粉丝来找我说: Mic老师,你说并发编程很重要,果然我今天又挂在一道并发编程的面试题上了. 我问他问题是什么,他说:"如何中断一个正在运行中的线程?". ...

  8. 浅谈Javascript单线程和事件循环

    单线程 Javascript 是单线程的,意味着不会有其他线程来竞争.为什么是单线程呢? 假设 Javascript 是多线程的,有两个线程,分别对同一个元素进行操作: function change ...

  9. 使用cmd命令行执行MySQL数据库

    说明 用命令提示符来操作一些简单的数据库,便捷又快速,随便记录一下,以后没事就自己来看看! 哈哈哈! 打开/关闭mysql服务 net start mysql net stop mysql 连接mys ...

  10. 文件输入输出处理-File

    大佬的理解-><IO流和File> 1.File类 File类是IO包中唯一代表磁盘文件本身的对象,File类定义了一些与平台无关的方法来操作文件.通过调用File类提供的各种方法, ...