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

    你可能感兴趣的文章
    Plotly-Dash:如何过滤具有多个数据框列的仪表板?
    查看>>
    Plotly:如何为 x 轴上的时间序列设置主要刻度线/网格线的值?
    查看>>
    Plotly:如何从 x 轴删除空日期?
    查看>>
    Plotly:如何从单条迹线制作堆积条形图?
    查看>>
    Plotly:如何以 Root 样式绘制直方图,仅显示直方图的轮廓?
    查看>>
    Plotly:如何使用 Plotly Express 组合散点图和线图?
    查看>>
    Plotly:如何使用 plotly.graph_objects 和 plotly.express 定义图形中的颜色?
    查看>>
    Plotly:如何使用 Python 对绘图对象条形图进行颜色编码?
    查看>>
    Plotly:如何使用 updatemenus 更新一个特定的跟踪?
    查看>>
    Plotly:如何使用长格式或宽格式的 pandas 数据框制作线图?
    查看>>
    Plotly:如何向烛台图添加交易量
    查看>>
    Plotly:如何在 plotly express 中找到趋势线的系数?
    查看>>
    Plotly:如何在桑基图中设置节点位置?
    查看>>
    Plotly:如何处理重叠的颜色条和图例?
    查看>>
    Plotly:如何手动设置 plotly express 散点图中点的颜色?
    查看>>
    Plotly:如何结合 make_subplots() 和 ff.create_distplot()?
    查看>>
    Plotly:如何绘制累积的“步骤“;直方图?
    查看>>
    Quartz进一步学习与使用
    查看>>
    Plotly条形图-根据正/负值更改颜色-python
    查看>>
    PLSQL developer12安装图解
    查看>>