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

    你可能感兴趣的文章
    pandas :按移位分组和累加和(GroupBy Shift And Cumulative Sum)
    查看>>
    pandas :检测一个DF和另一个DF之间缺失的列
    查看>>
    Pandas-从具有嵌套列表列表的现有列创建动态列时出错
    查看>>
    Pandas-通过对列和索引的值求和来合并两个数据框
    查看>>
    pandas.columns、get_dummies等用法
    查看>>
    pandas.DataFrame.copy(deep=True) 实际上并不创建深拷贝
    查看>>
    pandas.read_csv()的详解-ChatGPT4o作答
    查看>>
    PANDAS.READ_EXCEL()输出‘;溢出错误:日期值超出范围‘;而不存在日期列
    查看>>
    pandas100个骚操作:再见 for 循环!速度提升315倍!
    查看>>
    Pandas:如何根据其他列值的条件对列进行求和?
    查看>>
    Pandas:对给定列求和 DataFrame 行
    查看>>
    Pandas、groupby 和特定月份的求和
    查看>>
    Pandas、Matplotlib、Pyecharts数据分析实践
    查看>>
    Pandas中文官档 ~ 基础用法1
    查看>>
    Pandas中文官档~基础用法2
    查看>>
    SpringBoot+Vue+OpenOffice实现文档管理(文档上传、下载、在线预览)
    查看>>
    Pandas中文官档~基础用法5
    查看>>
    Pandas中文官档~基础用法6
    查看>>
    Pandas中的GROUP BY AND SUM不丢失列
    查看>>
    Pandas中的GROUP BY AND SUM不丢失列
    查看>>