博客
关于我
【luogu P6033】合并果子 加强版
阅读量:325 次
发布时间:2019-03-04

本文共 2681 字,大约阅读时间需要 8 分钟。

合并果子 加强版

题目链接:(待补充)

题目大意:

有一堆东西,每次你可以选两个东西,用它们大小的和的代价把它们合并,得到一个它们大小和的东西。目标是将所有东西合并成一个东西所要的最小代价。

普通的解法中,使用优先队列(堆)的时间复杂度是 O(n log n),但在数据量较大的情况下,这种方法无法通过时间限制。因此,我们需要一种更高效的算法。

思路:

  • 首先,我们需要明确普通解法的思路:使用优先队列(堆)来维护当前处理的最小两个数,从而合并得到最小代价。

  • 但由于数据量较大,普通的 O(n log n) 时间复杂度方法无法通过时间限制。因此,我们需要寻找更高效的方法。

  • 我们可以采用以下思路:首先对数据进行桶排(Bucket Sort),这可以在 O(n) 时间内完成数据的排序。对于大数据量,甚至可以使用基数排序(Frequency Sort)。

  • 接下来,我们需要维护一个队列(Queue)来存储生成的新数。每次合并两个最小的数,生成一个新的数,并将这个新数插入队列中。

  • 新生成的数一定比原来的数大,因此我们可以每次从队列中取出两个最小的数进行合并,直到队列中只剩下一个数为止。

  • 这种方法可以在 O(n) 时间内完成,因为每次合并都减少了一个数,最终需要 n-1 次合并操作。

  • 代码示例:

    手动队列版:

    #include 
    #include
    #define ll long longusing namespace std;int n;ll ans = 0;ll x, y, xx, yy, box[100001];ll q[10000001], p[10000001];ll t, tt;int read() { int re = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { re = re * 10 + c - '0'; c = getchar(); } return re;}int main() { n = read(); for (int i = 1; i <= n; i++) { x = 1ll * read(); box[x]++; } for (int i = 1; i <= 100000; i++) { for (int j = 1; j <= box[i]; j++) { q[++q[0]] = i; } } while (p[0] + q[0] - t - tt > 1) { x = q[t + 1]; xx = q[t + 2]; y = p[tt + 1]; yy = p[tt + 2]; if (xx < y && t + 2 <= q[0] || (tt + 1 > p[0])) y = xx, t += 2; else if (yy < x && tt + 2 <= p[0] || (t + 1 > q[0])) x = yy, tt += 2; else t++, tt++; ans += x + y; p[++p[0]] = x + y; if (p[0] + q[0] - t - tt <= 1) { break; } } printf("%lld", ans); return 0;}

    自带队列版:

    #include 
    #include
    #define ll long longusing namespace std;int n;ll ans = 0;ll x, y, xx, yy;queue
    q, p;int read() { int re = 0; char c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { re = re * 10 + c - '0'; c = getchar(); } return re;}int main() { n = read(); for (int i = 1; i <= n; i++) { x = 1ll * read(); x++; } for (int i = 1; i <= 200000; i++) { for (int j = 1; j <= box[i]; j++) { q.push(i); } } while (1) { if (q.empty() && p.empty()) break; ll min1 = q.front(); q.pop(); if (p.empty()) { if (q.empty()) break; ll min2 = p.front(); p.pop(); if (p.empty()) break; } if (min1 < min2) { x = min1; y = min2; } else { x = min2; y = min1; } ans += x + y; p.push(x + y); } printf("%lld", ans); return 0;}

    注:上述代码可能存在错误,具体请根据实际需求进行调试和优化。

    转载地址:http://ehvh.baihongyu.com/

    你可能感兴趣的文章
    python上的字无效字符_标识中的无效字符
    查看>>
    python下用decode和encode 中文转码
    查看>>
    Python下调用Linux的Shell命令
    查看>>
    Python接口自动化测试实战系列
    查看>>
    python下载_安装_配置_以及第一行python程序---python工作笔记009
    查看>>
    Python不协调机器人消息.内容
    查看>>
    Python与C#之间内存共享互传信息
    查看>>
    python与c语言混合编程_你试过C语言和Python一起混合编程吗?两者相加不是已经无敌了!...
    查看>>
    python与excel
    查看>>
    Python与Excel的完美邂逅:深入浅出,手把手教你轻松玩转Excel数据操作
    查看>>
    python与flask_Python编程中flask的简介与简单使用
    查看>>
    python与图灵机器人交互(WXPY版本)
    查看>>
    python与运算符_python运算符
    查看>>
    python两个列表获取交集,并集,差集
    查看>>
    python两个字典合并,两个list合并
    查看>>
    Python两个版本共存时,命令行升级pip
    查看>>
    Python两个版本共存时,怎么验证是否安装成功 scrapy
    查看>>
    Python两个版本共存时,通过pip安装Scrapy
    查看>>
    python两组变量的相关关系散点图_变量是什么?变量间的两种关系——函数关系和相关关系(小学版)...
    查看>>
    Python中 pass语句的作用
    查看>>