NC14291 Cut
题目
题目描述
给你一个长度为 的序列,你每次可以将一个序列分割成两个连续的的子序列,
分割的代价为原序列的总和。
现在允许你在初始时将序列重新排列一次。
问分割成 个长度为 的序列的最大总代价是多少?
输入描述
第一行一个数 表示原序列的长度;
接下来一行 个数 表示原序列的第 个数。
输出描述
一行一个整数表示答案。
示例1
输入
4 3 2 4 1
输出
26
说明
[3,2,4,1]重排->[1,2,3,4]->[1],[2,3,4]->[1],[2],[3,4]->[1],[2],[3],[4]。
示例2
输入
4 1 1 1 1
输出
9
题解
方法一
知识点:贪心,数学。
显然,每次把最小的取出来,大的加的机会就更多。
不妨再进一步思考,实际上从小到大取,第 个数会加 次。特别地,最后一个数只有 次,因为最后一次没有取。
所以有 。
时间复杂度
空间复杂度
方法二
知识点:贪心,优先队列。
贪心思路还是一样的,不过这次用优先队列傻瓜式维护即可。
不过需要注意的是,为了方便我们假设一个等价情形,元素还未合并,要求每次合并两段序列,使得最后花费最多。显然是从大的先合并,答案和从小开始的分割序列等价。于是,很容易用优先队列维护。
时间复杂度
空间复杂度
代码
方法一
#include <bits/stdc++.h> #define ll long long using namespace std; int a[100007]; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n; cin >> n; for (int i = 1;i <= n;i++) cin >> a[i]; sort(a + 1, a + 1 + n); ll ans = -a[n]; for (int i = 1;i <= n;i++) { ans += 1LL * i * a[i]; } cout << ans << '\n'; return 0; }
方法二
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n; cin >> n; priority_queue<ll> pq; for (int i = 0, tmp;i < n;i++) cin >> tmp, pq.push(tmp); ll ans = 0; for (int i = 0;i < n - 1;i++) { ll sum = pq.top(); pq.pop(); sum += pq.top(); pq.pop(); pq.push(sum); ans += sum; } cout << ans << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/16459887.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧