题目:
小Z很喜欢在果林里漫步,望着树上的果子,忍不住开始摘果子了。

他把果林里的n棵树上的果子都摘下来了(这也太过分了吧)!他还无聊地输出了每一棵果树上的果子个数$num[i]$。

小Z又决定把所有的果子都合成一堆。每一次合并,小Z把两堆果子合并到一起,消耗的体力为两堆果子的重量之和。显然,所有的果子经过$n-1$次合并后,就只剩下一堆了。小Z在合并果子时总共消耗的体力等于合并所耗体力之和。

由于小Z特别地懒,所以他想知道自己合并果子所消耗的体力最少为多少。

输入:

第一行,输入一个数n,表示果林中树的棵数。

第二行,包括n个数,第$i$个数$num_i$表示第i棵果树上的果子个数。

第三行,输入一个数q,表示有q组询问。

接下来q行,每次输出两个数l和r,表示将$[l,r]$区间内所有果树合并成一堆所对应的答案。
输出:

输出共q行,每次输出对应消耗的最少体力。

样例输入:
3
1 2 9
3
1 3
1 2
2 3

样例输出:
15
3
11

【数据范围】

对于30%的数据,$1 <= n <= 1000, 1 <= q <= 100, num_i <= 1e3$

对于60%的数据,$1 <= n <= 100000, 1 <= q <= 10, num_i <= 1e4$

对于100%的数据,$1 <= n <= 100000, 1 <= q <= 500, num_i <= 1e5$.

#数据不保证l<=r!

Solution

$Subtask #1$
将l到r的所有果子都扫一遍,每次排个序。
复杂度:$O(q * n^2 * logn)$,得分:30分。

$Subtask #2$
考虑到每次排个序有很多冗余的情况,且每次都是取最小的两个,自然想到用堆来维护l到r区间的果子。
每次取两次堆顶,并将合并后的数加入堆中即可。这些是堆的基本性质。
复杂度:$O(q*n*logn)$,得分:60分。

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const int maxn = 100005;
ll heap[maxn], cnt;
int a[maxn];
int n, q;void up(int u) {int fa = u >> 1;if (fa > 0) {if (heap[fa] > heap[u]) {swap(heap[fa], heap[u]);up(fa);}}
}
void down(int u) {int son = u << 1;if (son <= cnt) {if (son < cnt && heap[son + 1] < heap[son])son++;if (heap[u] > heap[son]) {swap(heap[u], heap[son]);down(son);}}
}int main() {scanf("%d", &n);for (int i = 1; i <= n; i++)scanf("%d", &a[i]);scanf("%d", &q);while (q--) {int l, r; scanf("%d %d", &l, &r);if (l > r) swap(l, r);cnt = 0;for (int i = l; i <= r; i++) {heap[++cnt] = a[i];up(cnt);}ll ans = 0;for (int i = l; i < r; i++) {ll ad = heap[1];heap[1] = heap[cnt--]; down(1);ad += heap[1];heap[1] = heap[cnt--]; down(1);ans += ad;heap[++cnt] = ad; up(cnt);}printf("%lld\n", ans);}return 0;
}

$Subtask #3$
题目中给出了果子数<=1e5,所以从这里突破,每次l到r区间的果子可以用桶排序来使得有序。
此时我们获得了一个单调队列(即单调递增)。同时我们再维护一个合并后的单调队列。
每次取两个最小的数,即为两次比较两个单调队列的队头大小,并每次取小的队头,并将合并后的数加到合并的单调队列的队尾即可。
复杂度:$O(qn)$,得分:100分。

代码:

#include <bits/stdc++.h>
using namespace std;#define clean(s, k) memset(s, k, sizeof(s))
#define RE register
#define rep(i, l, r) for (RE int i = l; i <= r; i++)
typedef long long ll;
const int maxn = 100005;
int a[maxn], cnt[maxn];
ll b[maxn], s[maxn];
int hb, tb, hs, ts;
int n, q, l, r;int read() {int num = 0;char op = getchar();while (!isdigit(op)) op = getchar();while (isdigit(op)) {num = 10 * num + op - '0';op = getchar();}return num;
}void pre() {clean(cnt, 0), clean(s, 0x7f); clean(b, 0x7f);hs = hb = 1, ts = tb = 0;int mn = 100000, mx = 0;rep(i, l, r) {cnt[a[i]]++;mn = min(mn, a[i]);mx = max(mx, a[i]);}rep(i, mn, mx)rep(j, 1, cnt[i])b[++tb] = i;
}ll calc() {ll ans = 0;rep(i, l, r - 1) {ll add = 0;if (b[hb] < s[hs]) add = b[hb++];else add = s[hs++];if (b[hb] < s[hs]) add += b[hb++];else add += s[hs++];ans += add;s[++ts] = add;}return ans;
}int main() {n = read();rep(i, 1, n)a[i] = read();q = read();rep(QAQ, 1, q) {l = read(), r = read();if (l > r) swap(l, r);pre();printf("%lld\n", calc());}return 0;
}

 

转载于:https://www.cnblogs.com/wlzhouzhuan/p/10161377.html

洛谷 T63713 合并果子相关推荐

  1. 洛谷P1090 合并果子

    合并果子 题目链接 这个只能用于结构体中 struct item {int val;friend bool operator < (item a,item b){return a.val > ...

  2. 洛谷——P1090 合并果子

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

  3. 洛谷1090 合并果子

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

  4. 洛谷 P1775 合并石子(弱化版)

    文章目录 合并石子(弱化版) 一.题目描述 二.思路 三.代码 合并石子(弱化版) 一.题目描述 https://www.luogu.com.cn/problem/P1775 设有 N(N \le 3 ...

  5. 洛谷 P2300 合并神犇 解题报告

    P2300 合并神犇 题目背景 loidc来到了NOI的赛场上,他在那里看到了好多神犇. 题目描述 神犇们现在正排成一排在刷题.每个神犇都有一个能力值p[i].loidc认为坐在附近的金牌爷能力参差不 ...

  6. 合并果子(洛谷-P1090)

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

  7. 贪心算法——洛谷(P1090)[NOIP2004]合并果子

    该题目也属于经典的贪心算法,在这里熟悉C++里优先队列的使用. 需要导入头文件:   #include<queue> 从这个问题可以深挖出神奇的哈夫曼树问题. 因为这题里合并的是二叉树,所 ...

  8. 【洛谷1090】合并果子

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

  9. P1090 合并果子 / [USACO06NOV] Fence Repair G(贪心+优先队列) 洛谷

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

最新文章

  1. 使用Redis分布式锁处理并发,解决超卖问题
  2. 斗地主案例的需求分析
  3. 一串事物中每个事物的前后位置与顺序编号的转换问题
  4. STM32F103_步进电机
  5. 微信“拍一拍”新增“炸一炸”功能;爱奇艺 CEO:会费涨价是行业必然趋势;微软终止 Windows 10X 开发|极客头条...
  6. SDWebImage常用方法及原理
  7. 深度deepin 20安装官方APP
  8. [NXP.iMX6UL] NFS服务器
  9. 中国科学技术大学研究生现代生物医药概论复习参考
  10. pinia 配置教程
  11. 全能第三方支付对接pay-java-parent 2.12.7 发布,支付聚合
  12. 【20G】Kaggle数据集强势分析“绝地求生”,攻略吃鸡!
  13. java多媒体论文_9000字JAVA论文:多媒体技术
  14. 你要知道的密评改造方案
  15. 暴风电视黑屏出现android,电视打开后黑屏怎么回事 电视打开后黑屏解决方法【图文详解】...
  16. INSERT INTO 和 INSERT IGNORE INTO
  17. 可变参数及Lambda表达式
  18. nc\hdf\h5数据格式批量提取为tif格式
  19. 比起尴尬的“免签”政策,马来西亚的美食美景要靠谱多了
  20. Photoshop肖像数字绘画中的照明和色彩艺术

热门文章

  1. 惊绝在世音乐《道禅》(典藏级)
  2. 软件测试员的思考问题方式(转)
  3. $.each与$().each的区别
  4. 项目实训- 基于unity的2D多人乱斗闯关游戏设计与开发(十1、FPS多人化——IK)
  5. Idea class模板(备忘录)
  6. 【直播回顾】技术大咖揭秘网络通信中的数据安全
  7. 存储相关概要–BigTable设计原理
  8. php批号管理,批号_序列号编码规则
  9. PHPCMS V9 实现下拉加载的方法,兼容手机端(附源码下载)
  10. 条码查询工具(Excel版)