浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=1150

显然,这题用贪心转化一下题意就是给你\(n-1\)个数,选\(k\)个不相邻的数权值和最小。

假设最小值是\(a_x\),那么选完\(a_x\)之后\(a_{x-1}\)和\(a_{x+1}\)就不能选了。

如果\(a_{x-1}\)和\(a_{x+1}\)只选了某一个,显然把这个换成\(a_x\)更优。

所以最优解要么有\(a_x\)没有\(a_{x-1}\)和\(a_{x+1}\),要么同时有\(a_{x-1}\)和\(a_{x+1}\)。

所以我们每次从堆里取出来一个数之后,再把它前一个数和后一个数在堆里删掉,往堆里塞一个\(a_{i-1}+a_{i+1}-a_i\)即可。这样就可以考虑这两种情况了。

如果取出的这个数前面没有数或者后面没有数,那么就不需要加\(a_{i-1}+a{i+1}-a_i\)进堆,而是把它后一个数或者前一个数也从堆里删掉。可以证明,如果选了当前这个数,那么与它相邻的那个数必然不会被选。因为选与它相邻的数之后所遇到的局面,选当前数也能到达,这个决策包涵了选相邻的数的决策,而且选当前数更优,所以与当前数相邻的那个数可以直接舍弃了。

时间复杂度:\(O((n+k)logn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std; const int maxn=1e5+5; int n,m,ans;
int a[maxn]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} struct Linked_List {
int lst,nxt,val,in_heap; Linked_List() {} Linked_List(int _lst,int _nxt,int _val) {
lst=_lst,nxt=_nxt,val=_val;
}
}L[maxn]; struct Heap {
int tot;
int tree[maxn]; bool less(int id1,int id2) {return L[id1].val<L[id2].val;} void up(int pos) {
while(pos>1) {
if(less(tree[pos],tree[pos>>1])) {
swap(tree[pos],tree[pos>>1]);
swap(L[tree[pos]].in_heap,L[tree[pos>>1]].in_heap);
pos>>=1;
}
else break;
}
} void down(int pos) {
int son=pos<<1;
while(son<=tot) {
if(son<tot&&less(tree[son|1],tree[son]))son|=1;
if(less(tree[son],tree[pos])) {
swap(tree[son],tree[pos]);
swap(L[tree[son]].in_heap,L[tree[pos]].in_heap);
pos=son,son=pos<<1;
}
else break;
}
} void ins(int v) {tree[++tot]=v,L[v].in_heap=tot,up(tot);} int pop() {
int res=tree[1];
tree[1]=tree[tot--];
L[tree[1]].in_heap=1;
down(1);return res;
} void del(int id) {
if(id==tot) {tot--;return;}
tree[id]=tree[tot--];
L[tree[id]].in_heap=id;
if(id==1)down(id);
else if(id==tot)up(id);
else up(id),down(id);
}
}T; int main() {
n=read(),m=read();
for(int i=1;i<=n;i++) {
a[i]=read();
if(i>1) {
L[i-1]=Linked_List(i-2,i,a[i]-a[i-1]);
T.ins(i-1);
}
}
while(m--) {
int id=T.pop(),lst=L[id].lst,nxt=L[id].nxt;
ans+=L[id].val;
if(!lst) {
T.del(L[nxt].in_heap);
L[L[nxt].nxt].lst=0;continue;
}
if(nxt==n) {
T.del(L[lst].in_heap);
L[L[lst].lst].nxt=n;continue;
}
T.del(L[lst].in_heap),T.del(L[nxt].in_heap);
L[lst].val=L[lst].val+L[nxt].val-L[id].val;T.ins(lst);
L[lst].nxt=L[nxt].nxt,L[L[nxt].nxt].lst=lst;
}
printf("%d\n",ans);
return 0;
}

BZOJ1150:[CTSC2007]数据备份的更多相关文章

  1. BZOJ1150 [CTSC2007]数据备份Backup 链表+小根堆

    BZOJ1150 [CTSC2007]数据备份Backup 题意: 给定一个长度为\(n\)的数组,要求选\(k\)个数且两两不相邻,问最小值是多少 题解: 做一个小根堆,把所有值放进去,当选择一个值 ...

  2. bzoj1150 [CTSC2007]数据备份Backup 双向链表+堆

    [CTSC2007]数据备份Backup Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2727  Solved: 1099[Submit][Stat ...

  3. BZOJ1150[CTSC2007]数据备份Backup——模拟费用流+堆+链表

    题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游 ...

  4. bzoj1150 [CTSC2007]数据备份

    Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中 ...

  5. BZOJ1150 [CTSC2007]数据备份Backup 【堆 + 链表】

    题目 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的 ...

  6. BZOJ1150 [CTSC2007] 数据备份Backup 贪心_堆_神题

    Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家 ...

  7. BZOJ1150 [CTSC2007]数据备份Backup 贪心 堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1150 题意概括 数轴上面有一堆数字. 取出两个数字的代价是他们的距离. 现在要取出k对数,(一个数 ...

  8. bzoj1150: [CTSC2007]数据备份Backup--贪心+优先队列维护堆

    题目大意:将k对点两两相连,求最小长度 易证得,最优方案中,相连的办公楼一定是取相邻的比取不相邻的要更优 然后就可以用贪心来做这道题了.. 之前向CZL大神学习了用堆来贪心的做法orz 大概思路就是将 ...

  9. bzoj1150: [CTSC2007]数据备份Backup

    题目大意: 在n个点中,选出k对相邻的互不相同的点,使k段距离的总和最小. 贪心,双向链表. 首先,点之间的距离是动态的,所以要用堆来维护.   每次都选择最近的点.但因为其他情况,可能最终不会选择这 ...

  10. 【BZOJ1150】[CTSC2007]数据备份Backup 双向链表+堆(模拟费用流)

    [BZOJ1150][CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此 ...

随机推荐

  1. shell脚本调试运行

    1.在命令行提供参数:$sh -x script.sh   但是有的shell脚本只能用 ./xxx.sh的方式运行,不能用sh命令解析执行.则此方法会报错.2.脚本开头提供参数:#!/bin/sh ...

  2. Tensorflow—gpu报错

    一晚上什么事都没做,就一直在查找tensorflow1.4缺少cudnn64_6的错误. 最后发现自己一直用的是cudnn64_7,即使改成cudnn64_6仍不可行.主要受实验室大佬安装的cudnn ...

  3. iOS UILabel 省略号 不变色 问题处理

    在我们公司 应用 4.1版本 我发现一个很有趣的问题 ,  当我修改 label 的 textColor  (默认单行情况)为黑色之外的颜色   省略号依然为黑色, 这个在iOS 7 iOS8.1 i ...

  4. 经典c语言题

    1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 2. 写一个“标 ...

  5. 每天一个Linux命令(11)nl命令

    nl命令读取 file 参数(缺省情况下标准输入),计算输入中的行号,将计算过的行号写入标准输出. 其默认的结果与cat -n有点不太一样, nl 可以将行号做比较多的显示设计,包括位数与是否自动补齐 ...

  6. [原创]java WEB学习笔记07:关于HTTP协议

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  7. Linux 上关于iptables

    有几个命令: 1.service iptables staus   2.service iptables start    3.service iptables restart   有个配置文件/ec ...

  8. SpringCloud之服务提供和服务调用的搭建

    pom文件: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3 ...

  9. dedecms 织梦点击图片进入下一页代码

    织梦DedeCMS5.6网站文章页点击图片进入下一页最后一页进入下一篇文章的方法: 我们首先按照下面的方法修改: 修改 include/arc.archives.class.php 1.查找“//解析 ...

  10. HDU 5869 Different GCD Subarray Query(2016大连网络赛 B 树状数组+技巧)

    还是想不到,真的觉得难,思路太巧妙 题意:给你一串数和一些区间,对于每个区间求出区间内每段连续值的不同gcd个数(该区间任一点可做起点,此点及之后的点都可做终点) 首先我们可以知道每次添加一个值时gc ...