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 ≤1000 000 000), 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。

Output

  输出应由一个正整数组成,给出将2K个相异的办公楼连成k对所需的网络电缆的最小总长度。

Sample Input

5 2
1
3
4
6
12

Sample Output

4
 
正解:堆+链表模拟费用流。
很显然,只有相邻两点之间会有边,所以这是一个二分图的模型。
但是直接跑费用流会挂,所以我们考虑优化。
因为这个图比较简单,所以我们可以用堆+链表来模拟费用流。
我们每次在堆里取一条最短路,增广一条路以后,这条路会反过来,那么我们把它的相反数和它在链上的前后两点的路径值加起来,建一个新点丢到堆里就行了。
感觉讲起来很玄学。。还是推荐一个博客吧:http://www.cnblogs.com/GXZlegend/p/7128426.html
 
 //It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define N (500010)
#define il inline
#define RG register
#define ll long long using namespace std; struct data{ int x; ll val; il bool operator < (const data &a) const{
return val>a.val;
} }; priority_queue <data> Q; int lst[N],nxt[N],del[N],n,k,tot;
ll dis[N],val[N],ans; il int gi(){
RG int x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
return q*x;
} int main(){
#ifndef ONLINE_JUDGE
freopen("backup.in","r",stdin);
freopen("backup.out","w",stdout);
#endif
n=gi(),k=gi(),tot=n-;
for (RG int i=;i<=n;++i) dis[i]=gi(),lst[i]=i-,nxt[i]=i+;
for (RG int i=;i<n;++i) Q.push((data){i,val[i]=dis[i+]-dis[i]});
nxt[n-]=nxt[n]=;
while (k--){
while (del[Q.top().x]) Q.pop(); RG int x=Q.top().x; Q.pop();
ans+=val[x],del[x]=del[lst[x]]=del[nxt[x]]=;
if (!lst[x]) lst[nxt[nxt[x]]]=;
else if (!nxt[x]) nxt[lst[lst[x]]]=; else{
val[++tot]=val[lst[x]]+val[nxt[x]]-val[x];
lst[tot]=lst[lst[x]],nxt[tot]=nxt[nxt[x]];
if (lst[tot]) nxt[lst[tot]]=tot;
if (nxt[tot]) lst[nxt[tot]]=tot;
Q.push((data){tot,val[tot]});
}
}
printf("%lld\n",ans); return ;
}

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]数据备份Backup 【堆 + 链表】

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

  5. BZOJ1150 [CTSC2007] 数据备份Backup 贪心_堆_神题

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

  6. BZOJ1150 [CTSC2007]数据备份Backup 贪心 堆

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1150 题意概括 数轴上面有一堆数字. 取出两个数字的代价是他们的距离. 现在要取出k对数,(一个数 ...

  7. bzoj1150: [CTSC2007]数据备份Backup--贪心+优先队列维护堆

    题目大意:将k对点两两相连,求最小长度 易证得,最优方案中,相连的办公楼一定是取相邻的比取不相邻的要更优 然后就可以用贪心来做这道题了.. 之前向CZL大神学习了用堆来贪心的做法orz 大概思路就是将 ...

  8. bzoj1150: [CTSC2007]数据备份Backup

    题目大意: 在n个点中,选出k对相邻的互不相同的点,使k段距离的总和最小. 贪心,双向链表. 首先,点之间的距离是动态的,所以要用堆来维护.   每次都选择最近的点.但因为其他情况,可能最终不会选择这 ...

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

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

随机推荐

  1. php和c++自带的排序算法

    PHP的 sort() 排序算法与 C++的 sort() 排序算法均为不稳定的排序算法,也就是说,两个值相同的数经过排序后,两者比较过程中还进行了交换位置,后期开发应主要这个问题

  2. 信息领域热词分析系统--python过滤

    利用python过滤去没用的词语,过滤的词语存储在停用文件中. #创建停用词表 def stopwordlist(): stopwords=[line.strip() for line in open ...

  3. getElementsByTagName 、 getElementsByName 、getElementById区别

    WEB标准下可以通过getElementById(), getElementsByName(), and getElementsByTagName()访问DOCUMENT中的任一个标签: getEle ...

  4. Win10通过SSH与树莓派Raspbain系统互传文件

    1.在Linux系统上安装ssh-server(由于Raspbain系统自带ssh-server,这个步骤可以省略) 查看ssh是否运行的命令: ps -ef | grep ssh 如果没有安装,则安 ...

  5. 剑指offer中经典的算法题之从头到尾打印链表

    话不多说上代码: 我自己的算法是: /** * public class ListNode { * int val; * ListNode next = null; * * ListNode(int ...

  6. SCAU 算法课的题

    8594 有重复元素的排列问题(优先做) 时间限制:1000MS  内存限制:1000K提交次数:1610 通过次数:656 题型: 编程题   语言: G++;GCC;VC Description ...

  7. Django重新整理

    1.母版的继承 #base<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset ...

  8. LeetCode 122.买卖股票的最佳时机(C++)

    给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必须在再次 ...

  9. [一点一滴.NET]前台线程和后台线程

    前台线程和后台线程就是通过线程实例的属性IsBackground=true or false来区分的. 新建一个线程是默认是后台线程. 前台线程全部执行完之后,才退出进程. 进程退出,所有的后台线程全 ...

  10. 查看服务器配置信息prtdiag与systeminfo实用命令

    UNIX(SUN服务器)bash-2.05# prtdiag -v系统配置:  Sun Microsystems  sun4u Sun Fire V890系统时钟频率:150 MHz内存大小:3276 ...