【luogu P3620】数据备份(反悔贪心 / 撤回贪心)

数据备份

题目链接:luogu P3620

题目大意

给你一个数轴上面的一些点,你要选若干个点对,使得每个点至多在一个点对中,而且要你最小化每个点对之间距离的和。

思路

首先考虑普通的贪心。
就是每次选费用最小的那个,然后把它两边可以选的删掉。

但是你可能选旁边两个而不选它更优,所以考虑一个撤回操作:
你选了之后删掉两个旁边的和自己之后,加入旁边两个减去自己的值,那选了这个就抵消了这次选自己的,然后选了旁边的。(总体来讲也是多选了一个)

然后因为你旁边可能早就被删了,那你要找到的是旁边第一个没有被删的,所以我们可以用双向链表来维护。

代码

#include<queue> #include<cstdio> #define ll long long using namespace std; struct pl { int val, l, r; }a[100001]; int n, k, x, lst; bool cnot[100001]; ll ans; struct node { int pl, val; }; bool operator <(node x, node y) { return x.val > y.val; } priority_queue <node> q; void Delete(int now) {//删掉它两边的点 a[a[a[now].l].l].r = now; a[a[a[now].r].r].l = now; a[now].l = a[a[now].l].l; a[now].r = a[a[now].r].r; } int main() { scanf("%d %d %d", &n, &k, &lst); for (int i = 1; i < n; i++) { scanf("%d", &x); a[i].l = i - 1; a[i].r = i + 1; a[i].val = x - lst; q.push((node){i, a[i].val}); lst = x; } a[0].val = a[n].val = 1e9 + 1e7;//注意边界是要尽可能不优 for (int i = 1; i <= k; i++) { while (cnot[q.top().pl]) q.pop(); node now = q.top(); q.pop(); ans += now.val; cnot[a[now.pl].l] = cnot[a[now.pl].r] = 1; a[now.pl].val = a[a[now.pl].l].val + a[a[now.pl].r].val - a[now.pl].val;//反悔的花费 q.push((node){now.pl, a[now.pl].val}); Delete(now.pl); } printf("%lld", ans); return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_P3620.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(44)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示