博客
关于我
【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/

    你可能感兴趣的文章
    PROFINET 模拟器使用教程
    查看>>
    Program type already present: android.support.v4.widget.EdgeEffectCompat
    查看>>
    PyTorch中文版官方教程来啦(附下载)
    查看>>
    Progress Kemp LoadMaster 远程命令执行漏洞复现(CVE-2024-1212)
    查看>>
    Project configuration is not up-to-date with pom.xml. Run Maven->Update Project
    查看>>
    Project Euler 15 Lattice paths
    查看>>
    Project Euler 48 Self powers( 大数求余 )
    查看>>
    Project Euler Problem 12: Highly divisible triangular number
    查看>>
    ProjectEuler 2
    查看>>
    projection介绍及EPSG:4326和EPSG:3857的投射转换
    查看>>
    project打开文件时,显示无法识别此文件格式?
    查看>>
    Prometheus + Grafana on Kubernetes部署
    查看>>
    prometheus + grafana进行服务器资源监控
    查看>>
    Prometheus Alertmanager 告警配置详解
    查看>>
    Prometheus Grafana 展示平台
    查看>>
    Prometheus pushgateway使用详解
    查看>>
    Prometheus 云原生 - Prometheus 数据模型、Metrics 指标类型、Exporter 相关
    查看>>
    Prometheus 云原生 - 基于 file_sd、http_sd 实现 Service Discovery
    查看>>
    Prometheus 云原生 - 微服务监控报警系统 (Promethus、Grafana、Node_Exporter)部署、简单使用
    查看>>
    Prometheus 云原生 - 监控 Linux、MySQL、Redis、RabbitMQ、Docker、SpringBoot 3.x
    查看>>