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. Ubuntu上的Python

    在Ubuntu如何查看Python版本 2版本命令:Python -V  (注意是大写) 3版本命令:Python3 -V Ubutun16上默认安装Python 2.7, Python3 将Pyth ...

  2. 3.Servlet(二)

    1.Servlet应用开发接口 对Servlet应用开发接口及功能的掌握,决定了是否能做好Servlet开发工作. GenericServlet抽象类 HttpServlet抽象类 2.Servlet ...

  3. Linux Vi/Vim 在插入模式下键盘右边数字键输入异常

    问题:Linux在 Vi/Vim 在编辑文件时遇到一个问题,当我在 Insert 模式下进行修改文件内容的时候,用到了键盘(104键,右边带数字键那种)进行数字输入,当我输入数字 “5” 时,插入的数 ...

  4. vue-cli构建项目添加网站ico的logo

    1.网上找一个把图片改成ico格式的网站,把logo改成ico格式,命名favicon.ico 2.将favicon.ico放入static目录 3.在index.html文件中引入 <link ...

  5. js字符串与数字之间的比较

    //1.纯数字之间比较 console.log(1<3);//true //2.纯字符串比较,先转成ASCII码,按位依次比较 console.log("1"<&quo ...

  6. [转]jQuery Mobile: Get data passed to page via changePage mobile.changePage

    本文转自:http://stackoverflow.com/questions/15840611/jquery-mobile-get-data-passed-to-page-via-changepag ...

  7. Oracle PL/SQL 实现excel PMT函数、PPMT函数

    PMT函数 1.每月本息金额  = (本金×月利率×(1+月利率)^还款月数)÷ ((1+月利率)^还款月数-1) ,in_financeAmount in number) return number ...

  8. 基于Python实现邮件发送

    import smtplibfrom email.mime.text import MIMETextemail_host = 'smtp.163.com' # 邮箱地址email_user = 'sz ...

  9. LeetCode 441.排列硬币(C++)

    你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币. 给定一个数字 n,找出可形成完整阶梯行的总行数. n 是一个非负整数,并且在32位有符号整型的范围内. 示例 ...

  10. Entity Framework Many to Many Relation Mapping(Entity Framework多对多关系映射)

    通常我们在做数据库设计时都会有两张表是多对多关系的时候,在数据库做多对多关系时候我们通常通过中间关联表来处理,那我们现在在EF中是如何处理的呢? 假设我们有如下关系,用户(User)包含多个角色(Ro ...