浅谈堆: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. OSI模型第三层网络层-初识路由协议

    1.路由协议: 顾名思义就是路由器所使用的协议. 分类: (1)按照作用范围分类,IGP(类型)内部网关协议(rip,ospf,isis),EGP(类型)边界路由协议(bgp) 把互联网比作整个世界土 ...

  2. struts2 获取表单数据封装到list和map集合

    一.获取封装表单数据到list集合 示例 获取用户输入的用户名和密码并输出用户名. jsp页面 list[0]表示list中的第一个user对象 Java代码 二.封装表单数据到map集合 示例 获取 ...

  3. hibernate 多对多操作(级联操作)

    一.级联保存 分别在用户和角色配置文件中在set标签中加入cascade="save-update": 示例:添加同时添加用户对象和角色对象并关联两个对象: 只需将角色放入用户对象 ...

  4. Js编写的菜单树

    只需要提供这种JSON格式就ok了 其他的都可以直接引用这个代码进去 var testMenu=[ { "name": "一级菜单", "submen ...

  5. ALV 表头 ADD_TEXT

    [转自http://lz357502668.blog.163.com/blog/static/16496743201252891452493/] CALL METHOD valid_reference ...

  6. C语言程序设计50例(经典收藏)之1

    题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. #includ ...

  7. mysql 修改表名的方法:sql语句

    在使用mysql时,经常遇到表名不符合规范或标准,但是表里已经有大量的数据了,如何保留数据,只更改表名呢? 可以通过建一个相同的表结构的表,把原来的数据导入到新表中,但是这样视乎很麻烦. 能否简单使用 ...

  8. Shell传参的多种方式

    Shell 传参的多种方式 使用$1 $2 这种类似占位符的方式 # 命令行调用 start.sh 8080 9090 # 脚本中获取 port1=$1 # 8080 port2=$2 # 9090 ...

  9. rest-client restclient get post写法

    get url = "https://api.weixin.qq.com/sns/jscode2session" data = { appid: "××××", ...

  10. 小程序连接百度ai

    function getTextFromImage(res) { var access_token = '24.c649256d2e*****0.282335-11449805'; var url = ...