[CTSC2007]数据备份Backup (贪心)
题面
Description
你在一家 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 的网络电缆,满足距离之和最小的要求。
Input
第一行包含整数 n 和 k
其中 n(2 ≤ n ≤ 100 000)表示办公楼的数目,k(1 ≤ k ≤ n/2)表示可利用的网络电缆的数目。
接下来的 n 行每行仅包含一个整数(0 ≤ s ≤ 1 000 000 000),表示每个办公楼到大街起点处的距离。
这些整数将按照从小到大的顺序依次出现。
Output
输出应由一个正整数组成,给出将 2K 个相异的办公楼连成 k 对所需的网络电缆的最小总长度。
Sample Input
5 2
1
3
4
6
12
Sample Output
4
题解
首先,选的每一对楼肯定是相邻的两幢,所以,题意转化为在原数组的差分数组上选
k
k
k 个不相邻的数,使得总和最小。
然后,我发现它不能直接转化成拟阵,因为不满足交换性,也就是中间选的数会使得两边相邻的数不能被选。
于是我们用了一个类似反悔贪心的做法:
先找到差分数组中最小的一个,拿出来,设其为第
i
i
i 个数,那么接下来,可以证明
i
−
1
i-1
i−1 和
i
+
1
i+1
i+1 要么不选,要么同时选。反证法就行,若只选其中一个,同时
i
i
i 不能被选,这一定不如选
i
i
i 更优。
那么,
i
−
1
i-1
i−1 和
i
+
1
i+1
i+1 ——选
i
i
i 能影响到的所有位置——就是绑定在一起了,要么不选他们,保留
i
i
i ,选择的总数不变,要么选择它们,撤销掉
i
i
i ,选择的总数+1,同时影响
i
−
2
i-2
i−2 和
i
+
2
i+2
i+2 。
怎么看,我们都可以把
i
−
1
,
i
,
i
+
1
i-1,i,i+1
i−1,i,i+1 三个位置删掉,再在原位置插入一个
S
i
−
1
+
S
i
+
1
−
S
i
S_{i-1}+S_{i+1}-S_i
Si−1+Si+1−Si ,来转换这个复杂的过程。
最后就剩模拟了,
有自虐倾向精益求精 的人,可以打个平衡树模拟,讲效率 的人,可以打优先队列+链表。
CODE
我自诩精神正常
#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<ctime>
#include<queue>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define eps (1e-9)
#define SQ 447
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f*x;
}
void putpos(LL x) {
if(!x) return ;
putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
if(!x) putchar('0');
else if(x < 0) putchar('-'),putpos(-x);
else putpos(x);
}
const int MOD = 1000000007;
int n,m,s,o,k;
LL a[MAXN];
struct it{
int x;LL s;it(){x=s=0;}
it(int X,LL S){x=X;s=S;}
};
bool operator < (it a,it b) {return a.s < b.s;}
bool operator > (it a,it b) {return b < a;}
priority_queue<it,vector<it>,greater<it> > b;
int nl[MAXN],nr[MAXN];
bool f[MAXN];
void del(int x) {
int s = nl[x],o = nr[x];
nr[s] = o; nl[o] = s;
f[x] = 1; return ;
}
int main() {
n = read(); k = read();
for(int i = 1;i <= n;i ++) {
a[i] = read();
}
for(int i = 1;i < n;i ++) {
a[i] = a[i+1]-a[i];
nl[i] = i-1; nr[i] = i+1;
b.push(it(i,a[i]));
}
a[0] = a[n] = 1e16;
LL ans = 0;
for(int i = 1;i <= k;i ++) {
it t = b.top();b.pop();
while(f[t.x]) t = b.top(),b.pop();
ans += t.s;
s = nl[t.x]; o = nr[t.x];
a[t.x] = a[s] + a[o] - t.s;
b.push(it(t.x,a[t.x]));
del(s); del(o);
}
printf("%lld\n",ans);
return 0;
}
[CTSC2007]数据备份Backup (贪心)的更多相关文章
- BZOJ1150 [CTSC2007] 数据备份Backup 贪心_堆_神题
Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家 ...
- BZOJ1150 [CTSC2007]数据备份Backup 贪心 堆
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1150 题意概括 数轴上面有一堆数字. 取出两个数字的代价是他们的距离. 现在要取出k对数,(一个数 ...
- 【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列+双向链表)
1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设 ...
- 【链表】bzoj 1150: [CTSC2007]数据备份Backup
1150: [CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1136 Solved: 458[Submit] ...
- 1150: [CTSC2007]数据备份Backup
1150: [CTSC2007]数据备份Backup https://lydsy.com/JudgeOnline/problem.php?id=1150 分析: 堆+贪心. 每次选最小的并一定是最优的 ...
- bzoj1150 [CTSC2007]数据备份Backup 双向链表+堆
[CTSC2007]数据备份Backup Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2727 Solved: 1099[Submit][Stat ...
- 【BZOJ1150】[CTSC2007]数据备份Backup 双向链表+堆(模拟费用流)
[BZOJ1150][CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此 ...
- BZOJ1150 [CTSC2007]数据备份Backup 链表+小根堆
BZOJ1150 [CTSC2007]数据备份Backup 题意: 给定一个长度为\(n\)的数组,要求选\(k\)个数且两两不相邻,问最小值是多少 题解: 做一个小根堆,把所有值放进去,当选择一个值 ...
- 【bzoj1150】[CTSC2007]数据备份Backup 模拟费用流+链表+堆
题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公楼彼此之间互相备份,而你则坐在家中尽享计算机游戏 ...
随机推荐
- 【lora无线数传通信模块】亿佰特E22串口模块用于物联网地震预警传感通信方案
物联网地震预警项目介绍: 地震,俗称地动.它像平常的刮风下雨一样,是一种常见的自然现象,是地壳运动的一种表现,即地球内部缓慢积累的能量突然释放而引起的地球表层的振动.据统计,5级以上地震就能够造成破坏 ...
- dubbo容错机制
dubbo的容错机制 Failover Cluster(默认) 失败自动切换,当出现失败,重试其它服务器.通常用于读操作,但重试会带来更长延迟. Failfast Cluster 快速失败,只发起一次 ...
- 【Java集合】ArrayDeque源码解读
简介 双端队列是一种特殊的队列,它的两端都可以进出元素,故而得名双端队列. ArrayDeque是一种以循环数组方式实现的双端队列,它是非线程安全的. 它既可以作为队列也可以作为栈. 继承体系 Arr ...
- java标识符 identifier
1,标识符 --> 类名 方法名 变量名 常量名 接口名 为程序员自己命名的内容 main也是标识符但是不能修改 2, 命名规则 只能以 数字 字母(中文) 下划线 美元符号 ...
- 记一次ms17-010复现过程
最近碰到业务需要使用msf,以前了解过,后面都忘记了.这次干脆写下来,省的每次去找别人写的. 首先是使用nmap探测端口 nmap -O -sV 192.168.153.130 --script=vu ...
- SAP Web Dynpro-版本管理
您可以使用版本管理来管理对象的旧版本,比较版本,也可以重置它们. 在版本管理中,您可以存储ABAP开发对象的不同版本. 在ABAP工作台中,您可以比较不同版本的- 视图 视窗 控制器 您也可以存储对象 ...
- 隐私计算FATE-离线预测
一.说明 Fate 的模型预测有 离线预测 和 在线预测 两种方式,两者的效果是一样的,主要是使用方式.适用场景.高可用.性能等方面有很大差别:本文分享使用 Fate 基于 纵向逻辑回归 算法训练出来 ...
- bat-设置oracle服务
1.停止oracle所有服务 并将服务设置为手动启动 @echo off echo oracle服务--------停止 net stop OracleVssWriterORCL net stop O ...
- PTA(BasicLevel)-1018 锤子剪刀布
一.问题定义 大家应该都会玩"锤子剪刀布"的游戏:两人同时给出手势,胜负规则如下: 剪刀 > 布, 锤子 > 剪刀, 布 > 锤子 现给出两人的交 ...
- Linux sed工具的使用
基础知识 - 行编辑工具: 一行一行处理文件内容 - 全屏编辑工具:一次性将文件所有内容加载到内存中 sed编辑器: Stream Editor 工作原理: 逐行处理文件内容,一次读取一行内容到模式空 ...