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

其实说白了,这个题目的题意就是说,对于一组数进行差分,找出k个数两两不相邻使选取的数最少
首先有一种很容易想到的nk的算法,就是进行DP,不过在这里需要滚动,因为内存不够,用f[i,j]表示到第i个点的时候选了j个,这个转移比较简单,就不再多说了
下面我们来看正解,这个题目的做法很多,这里讲一下贪心的做法。
首先,直接贪心肯定是不对的,比如4,3,5,10,贪心的结果是13,但是显然结果应该是9,所以这里的贪心就是带反悔的(这种思想有点像网络流,所以有大佬说这个是模拟费用流,但是我不会emmm)。
怎么反悔呢?
每去除来一个点i,我们就要把i和两边的点给删去,和ans+s[i]相反的就是ans+s[i-1]+s[i+1],所以,我们需要的是在删去i之后加上一个值为s[i-1]+s[i+1]-s[i]的点,这样的话,如果取了两边点,两次加起来就是s[i-1]+s[i+1]-s[i]+s[i]=s[i-1]+s[i+1],相当于取了两边的点。
对于这个的维护,可以用堆,可以用平衡树(其实我觉得用平衡树好维护一些,但是懒得慌,就打了优先队列)

AC代码如下:

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define re register
#define gc getchar()
#define ll long long
#define il inline
const int N=,lim=(<<);
const ll INF=1e9;
il int read() {
re int x(),f();
re char ch=gc;
while(ch<''||ch>'') {
if(ch=='-') f=-;
ch=gc;
}
while(ch>=''&&ch<='') {
x=(x<<)+(x<<)+(ch^);
ch=gc;
}
return x*f;
}
struct node {
long long x,id;
bool operator < (const node & a) const {
return x>a.x;
}
};
priority_queue <node> q;
int n,k,s[N],la[N],ne[N];
bool vis[N];
int main() {
n=read(),k=read();
for(int i=; i<=n; ++i)
s[i]=read();
for(int i=; i<n; ++i) {
s[i]=s[i+]-s[i];la[i]=i-,ne[i]=i+;
q.push((node){
s[i],i
});
}
s[n]=s[]=INF;
int num=;
long long ans=;
for(re int i=; i<=k; ++i) {
node a;
while(vis[q.top().id]&&!q.empty())
q.pop();
a=q.top(),q.pop();
ans+=a.x;
int l=la[a.id],r=ne[a.id];
s[a.id]=s[l]+s[r]-s[a.id];
ne[la[l]]=ne[l],la[ne[l]]=la[l],la[l]=ne[l]=;
ne[la[r]]=ne[r],la[ne[r]]=la[r],la[r]=ne[r]=;
vis[l]=vis[r]=;
q.push((node) {
s[a.id],a.id
});
}
cout<<ans;
return ;
}

题解:[APIO/CTSC 2007]数据备份的更多相关文章

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

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

  2. P3620 [APIO/CTSC 2007]数据备份

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

  3. 洛谷 P3620 [APIO/CTSC 2007]数据备份 解题报告

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

  4. [luogu3620][APIO/CTSC 2007]数据备份【贪心+堆+链表】

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

  5. [APIO/CTSC 2007]数据备份(贪心+堆)

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

  6. 洛谷P3620 [APIO/CTSC 2007] 数据备份 [堆,贪心,差分]

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

  7. P3620 [APIO/CTSC 2007]数据备份[优先队列+贪心]

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

  8. 题解 P3620 【[APIO/CTSC 2007]数据备份】

    直接贪心(每次选最小)的话显然不对...样例都过不了... 选两个办公楼的时候,显然不能跨越另一个楼,这样不优... 于是 先把原数列处理成n-1个的数(每一个办公楼和上一个的距离),存在a[]中 题 ...

  9. [APIO/CTSC 2007]数据备份

    嘟嘟嘟 这竟然是一道贪心题,然而我在不看题解之前一直以为是dp. 首先最优的配对一定是相邻两个建筑物配对,所以我们求出差分数组,就变成了在n - 1个数中选出不相邻的k个数,使这k个数的和最小. 贪心 ...

随机推荐

  1. Netty学习笔记(四) 简单的聊天室功能之服务端开发

    前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...

  2. 章节九、1-Selenium环境配置

    一.Selenium环境安装配置,这里使用Selenium WebDriver 3.6.0 1.下载Selenium WebDriver (点击后网站响应比较慢,需要多等等) 2.打开该网址后点击“d ...

  3. SQLServer之创建表值函数

    表值函数创建注意事项 用户定义表值函数返回 table 数据类型. 对于内联表值函数,没有函数主体,表是单个 SELECT 语句的结果集. 表值函数主要用于数据计算出来返回结果集. 使用SSMS数据库 ...

  4. 数据库之redis篇(2)—— redis配置文件,常用命令,性能测试工具

    redis配置 如果你是找网上的其他教程来完成以上操作的话,相信你见过有的启动命令是这样的: 启动命令带了这个参数:redis.windows.conf,由于我测试环境是windows平台,所以是这个 ...

  5. C#微信支付对接

    c#版在pc端发起微信扫码支付   主要代码: /** * 生成直接支付url,支付url有效期为2小时,模式二 * @param productId 商品ID * @return 模式二URL */ ...

  6. python模块(os,sys,hashlib,collections)

    列出目录下所有文件 os.listdir('dirname'):列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式返回. 创建文件夹: os.mkdir('文件夹')    创建文件夹 os ...

  7. Linux/Unix环境下的make命令详解

    https://blog.csdn.net/wxqian25/article/details/21226711

  8. MySQL的Limit详解

    问题:数据库查询语句,如何只返回一部分数据? Top子句 TOP 子句用于规定要返回的记录的数目.对于拥有数千条记录的大型表来说,TOP 子句是非常有用的. 在SQL Server数据库中语法为: S ...

  9. XML详解一XML语法

    XML指可扩展标记语言很类似 HTML,被设计用来传输和存储数据而非显示数据,XML标签没有被预定义需要自行定义标签,标签具有自我描述性,同时XML也是 W3C 的推荐标准. 先来写一个XML脚本de ...

  10. 磁盘缓存--YYCache 设计思路

    为了设计一个比较好的磁盘缓存,我调查了大量的开源库,包括 TMDiskCache.PINDiskCache.SDWebImage.FastImageCache 等,也调查了一些闭源的实现,包括 NSU ...