浅谈堆: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)\)

代码如下:

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. const int maxn=1e5+5;
  5. int n,m,ans;
  6. int a[maxn];
  7. int read() {
  8. int x=0,f=1;char ch=getchar();
  9. for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
  10. for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
  11. return x*f;
  12. }
  13. struct Linked_List {
  14. int lst,nxt,val,in_heap;
  15. Linked_List() {}
  16. Linked_List(int _lst,int _nxt,int _val) {
  17. lst=_lst,nxt=_nxt,val=_val;
  18. }
  19. }L[maxn];
  20. struct Heap {
  21. int tot;
  22. int tree[maxn];
  23. bool less(int id1,int id2) {return L[id1].val<L[id2].val;}
  24. void up(int pos) {
  25. while(pos>1) {
  26. if(less(tree[pos],tree[pos>>1])) {
  27. swap(tree[pos],tree[pos>>1]);
  28. swap(L[tree[pos]].in_heap,L[tree[pos>>1]].in_heap);
  29. pos>>=1;
  30. }
  31. else break;
  32. }
  33. }
  34. void down(int pos) {
  35. int son=pos<<1;
  36. while(son<=tot) {
  37. if(son<tot&&less(tree[son|1],tree[son]))son|=1;
  38. if(less(tree[son],tree[pos])) {
  39. swap(tree[son],tree[pos]);
  40. swap(L[tree[son]].in_heap,L[tree[pos]].in_heap);
  41. pos=son,son=pos<<1;
  42. }
  43. else break;
  44. }
  45. }
  46. void ins(int v) {tree[++tot]=v,L[v].in_heap=tot,up(tot);}
  47. int pop() {
  48. int res=tree[1];
  49. tree[1]=tree[tot--];
  50. L[tree[1]].in_heap=1;
  51. down(1);return res;
  52. }
  53. void del(int id) {
  54. if(id==tot) {tot--;return;}
  55. tree[id]=tree[tot--];
  56. L[tree[id]].in_heap=id;
  57. if(id==1)down(id);
  58. else if(id==tot)up(id);
  59. else up(id),down(id);
  60. }
  61. }T;
  62. int main() {
  63. n=read(),m=read();
  64. for(int i=1;i<=n;i++) {
  65. a[i]=read();
  66. if(i>1) {
  67. L[i-1]=Linked_List(i-2,i,a[i]-a[i-1]);
  68. T.ins(i-1);
  69. }
  70. }
  71. while(m--) {
  72. int id=T.pop(),lst=L[id].lst,nxt=L[id].nxt;
  73. ans+=L[id].val;
  74. if(!lst) {
  75. T.del(L[nxt].in_heap);
  76. L[L[nxt].nxt].lst=0;continue;
  77. }
  78. if(nxt==n) {
  79. T.del(L[lst].in_heap);
  80. L[L[lst].lst].nxt=n;continue;
  81. }
  82. T.del(L[lst].in_heap),T.del(L[nxt].in_heap);
  83. L[lst].val=L[lst].val+L[nxt].val-L[id].val;T.ins(lst);
  84. L[lst].nxt=L[nxt].nxt,L[L[nxt].nxt].lst=lst;
  85. }
  86. printf("%d\n",ans);
  87. return 0;
  88. }

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. EasyNVR无插件直播服务器软件览器低延时播放监控摄像头视频(EasyNVR播放FLV视频流)

    背景描述 EasyNVR的使用者应该都是清楚的了解到,EasyNVR一个强大的功能就是可以进行全平台的无插件直播.主要原因在于rtsp协议的视频流(默认是需要插件才可以播放的)经由EasyNVR处理可 ...

  2. <%%>与<scriptrunat=server>,<%=%>与<%#%>的区别(转)

    这些东西都是asp.net前台页面与后台代码交互过程中经常使用的,它们之间有的非常相似,又有一些不同.对比学习下,看看他们之间的联系与区别. 首先看<%%>与<scriptrunat ...

  3. 九度OJ 1333:考研海报 (区间操作)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:738 解决:299 题目描述: sun是万千考研学子中的一员,他每天过着三点一线的生活. 学校里有一个公告栏,他每天都看到上面张贴着各种考研 ...

  4. tomcat日志按天切分

    1. 下载工具cronolog wget http://cronolog.org/download/cronolog-1.6.2.tar.gz 这是网上流传的下载地址,好像没用,所以需要自己去网上找. ...

  5. MySQL时间函数-获取当前时间-时间差

    MySQL中获取当前时间为now(),不同于sqlserver getdate(). SQLServer转MySQL除变化top 1 -> limit 1之后报错: limit [Err] 15 ...

  6. Android笔记之获取debug.keystore和release.keystore的MD5/SHA1值

    获取debug.keystore的key,如下图 获取release.keystore的key 输入命令keytool -list -v -keystore <jksFilename> 例 ...

  7. [ACM] FZU 2087 统计数边 (有多少边至少存在一个最小生成树里面)

    Problem Description 在图论中,树:随意两个顶点间有且仅仅有一条路径的图. 生成树:包括了图中全部顶点的一种树. 最小生成树:对于连通的带权图(连通网)G,其生成树也是带权的. 生成 ...

  8. ubuntu导入torch模块报错

    ubuntu下导入torch报错 >>> import torchIllegal instruction (core dumped) 安装pytorch 去pytorch官网下载py ...

  9. butterknif

    // butterknife public class ButterknifeActivity extends Activity { @butterknife.Bind(R.id.tv_title) ...

  10. iOS 图文混排 链接 可点击

    对于这个话题 我想到 1 第一个解决方法就是使用 webView 比较经典 把所有复杂工作都交给控件本身去处理了,  但是好像好多需要自定义的地方 没法从 webView获得响应回调 :(估计也可以实 ...