https://www.lydsy.com/JudgeOnline/problem.php?id=1150

你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份。然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏的乐趣。
已知办公楼都位于同一条街上。你决定给这些办公楼配对(两个一组)。每一对办公楼可以通过在这两个建筑物之间铺设网络电缆使得它们可以互相备份。
然而,网络电缆的费用很高。当地电信公司仅能为你提供 K 条网络电缆,这意味着你仅能为 K 对办公楼(或总计2K个办公楼)安排备份。任一个办公楼都属于唯一的配对组(换句话说,这 2K个办公楼一定是相异的)。
此外,电信公司需按网络电缆的长度(公里数)收费。因而,你需要选择这 K 对办公楼使得电缆的总长度尽可能短。换句话说,你需要选择这 K 对办公楼,使得每一对办公楼之间的距离之和(总距离)尽可能小。
下面给出一个示例,假定你有 5 个客户,其办公楼都在一条街上,如下图所示。这 5 个办公楼分别位于距离大街起点 1km, 3km, 4km, 6km 和 12km 处。电信公司仅为你提供 K=2 条电缆。
上例中最好的配对方案是将第 1 个和第 2 个办公楼相连,第 3 个和第 4 个办公楼相连。这样可按要求使用 K=2 条电缆。第 1 条电缆的长度是 3km-1km=2km ,第 2 条电缆的长度是 6km-4km=2km。这种配对方案需要总长 4km 的网络电缆,满足距离之和最小的要求。

一道需要些简单思(trick)维的题。

发现了我们只能取相邻两个办公楼之后我们就能够写出dp了,就不说了。

正解考虑贪心去取:我们将每一对办公楼的距离加入到堆里面,然后每次弹出最小,并且弹出的两侧办公楼对就不能再取了。是否可以呢?

显然是不行的,你会发现样例就是个反例:2 1 2 6,你取完1之后只能取6,结果输出了7。

于是我们要给程序一个“后悔“的机会:将弹出的两侧办公楼对合为一对,其距离为两个办公楼对的距离和-弹出的办公楼距离。

这样我们取这个对的时候就相当于减去了中间的对而取了旁边两侧的对,就是一个“后悔”的过程啦!

维护两侧的对可以用链表来实现。

#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define fi first
#define se second
const int N=1e5+;
const int INF=1e9+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
map<pii,bool>mp;
priority_queue<pii,vector<pii>,greater<pii> >q;
int n,k,a[N],pre[N],nxt[N];
int main(){
n=read(),k=read();
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<n;i++){
a[i]=a[i+]-a[i];
pre[i]=i-;nxt[i-]=i;
q.push(pii(a[i],i));
}
nxt[n-]=n;pre[]=;nxt[n]=n;a[]=a[n]=INF;
int ans=;
while(k--){
pii p=q.top();q.pop();
if(mp.count(p)){k++;mp.erase(p);continue;}
ans+=p.fi;
a[p.se]=a[pre[p.se]]+a[nxt[p.se]]-p.fi;
mp[pii(a[pre[p.se]],pre[p.se])]=;
mp[pii(a[nxt[p.se]],nxt[p.se])]=;
q.push(pii(a[p.se],p.se));
pre[p.se]=pre[pre[p.se]];
nxt[p.se]=nxt[nxt[p.se]];
nxt[pre[p.se]]=p.se;
pre[nxt[p.se]]=p.se;
}
printf("%d\n",ans);
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

+++++++++++++++++++++++++++++++++++++++++++

BZOJ1150:[APIO/CTSC2007]数据备份——题解的更多相关文章

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

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

  2. 【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆

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

  3. [APIO / CTSC2007]数据备份 --- 贪心

    [APIO / CTSC 2007]数据备份 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份. 然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公 ...

  4. BZOJ1150:[CTSC2007]数据备份

    浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...

  5. 【bzoj1150】[CTSC2007]数据备份Backup

    将k对点两两相连,求最小长度 易证得,最优方案中,相连的办公楼一定是取相邻的比取不相邻的要更优 然后就可以用贪心来做这道题了.. 将初始所有的线段放进堆里 每次取最短的线段进行连接,且ans+=a[i ...

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

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

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

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

  8. 洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心)

    洛谷P1484 种树&洛谷P3620 [APIO/CTSC 2007]数据备份 题解(堆+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/132 ...

  9. 【链表】bzoj 1150: [CTSC2007]数据备份Backup

    1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1136  Solved: 458[Submit] ...

随机推荐

  1. iFIERO - (一) 宇宙大战 SPACE BATTLE — 场景SCENE、SpriteKit精灵、PARTICLE粒子及背景音乐

    开始游戏教程前,首先介绍一下SpriteKit是什么?SpriteKit提供了一个图形渲染和动画的基础结构,你可以使用它让任意类型的纹理图片或者精灵动起来.SpriteKit使用渲染循环,利用图形硬件 ...

  2. String字符串的方法

    String字符串在Java开发中是我们常用的一种数据类型,同时String字符串也为我们提供了大量的方法.通过一些实例的练习,我们可以对String字符串的方法有一个比较清楚的了解. 有一个字符串S ...

  3. WinDbg使用学习

    拿到软件崩溃之后产生的crash文件,后缀名为dump 使用winDbg的File-----> Open Crash Dump 打开Crash文件 File---------> Symbo ...

  4. 机器学习算法 --- Naive Bayes classifier

    一.引言 在开始算法介绍之前,让我们先来思考一个问题,假设今天你准备出去登山,但起床后发现今天早晨的天气是多云,那么你今天是否应该选择出去呢? 你有最近这一个月的天气情况数据如下,请做出判断. 这个月 ...

  5. thinkphp 3.x下的任意文件包含(有条件)分析

    漏洞原理 实现自己的模版引擎不当,在模版渲染的情况下存在任意变量覆盖漏洞.. 漏洞详情 漏洞位置1 ThinkPHP/Library/Think/View.class.php 需要修改配置文件 指定T ...

  6. [salt] jinja模板中变量使用pillar的几种方法

    先转载下jinja模板中使用变量的方法,后文主要讲解pillar的变量使用方法 一.jinja模版的使用方法: 1.file状态使用template参数 - template:jinja 2.模版文件 ...

  7. centos7安装oracle亲测可用

    http://www.linuxidc.com/Linux/2016-04/130559p2.htm

  8. First Blood

    自我介绍 大家好!我的名字是戴俊涵,代号211606359,喜欢看电影和古风音乐,也是一个资深漫迷(让世界感受痛楚吧),喜欢的美食是牛排. 回想初衷 (1)回想一下你初入大学时对本专业的畅想 当初你是 ...

  9. C++:模板——函数模板1

    一.为什么使用函数模板 假设我们在程序中需要比较两个变量的大小,但变量的类型可能是int.float或者double,此时为了满足程序的要求我们可能会在程序中编写多个函数,如: //比较两个int型变 ...

  10. 冲刺One之站立会议8 /2015-5-21

    今天我们把聊天界面做了优化和改进,主要实现了聊天的功能.显示了正在进行通信的成员列表,和当前状态,是否连通和正常通信,大体完成了预期的目标. 燃尽图8