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


    [CTSC2007]数据备份Backup

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2727  Solved: 1099
    [Submit][Status][Discuss]

    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≤100000)表示办公楼的数目,k(1≤k≤n/2)表示可利用的网络电缆的数目。
    接下来的n行每行仅包含一个整数(0≤s≤1000000000),表示每个办公楼到大街起点处的距离。
    这些整数将按照从小到大的顺序依次出现。

    Output

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

    Sample Input

    5 2
    1
    3
    4
    6
    12

    Sample Output

    4

    HINT

    Source

    题解:这是一个双向链表的题目,可以将题目转化为给你n-1个距离,

    取k个不相相邻的值,那么就是将 k选了后,k-1,k+1 合并即可,a[k-1]+a[k+1]-a[k]

    为什么这样可以。

    如果不是选相邻的两个,那么没必要选a[k],差不多就这样吧。

     1 #pragma GCC optimize(2)
     2 #pragma G++ optimize(2)
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<queue>
     9 
    10 #define inf 2000000007
    11 #define ll long long
    12 #define fzy pair<ll,int>
    13 #define N 200007
    14 using namespace std;
    15 inline int read()
    16 {
    17     int x=0,f=1;char ch=getchar();
    18     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    19     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    20     return x*f;
    21 }
    22 
    23 ll ans;
    24 int n,m;
    25 ll a[N],pre[N],nxt[N];
    26 bool flag[N];
    27 priority_queue<fzy,vector<fzy>,greater<fzy> >q;
    28 
    29 void del(int p)
    30 {
    31     if (p==0||p==n+1) return;
    32     flag[p]=true;
    33     int l=pre[p],r=nxt[p];
    34     nxt[p]=pre[p]=0;
    35     nxt[l]=r,pre[r]=l;
    36 }
    37 void solve()
    38 {
    39     while(flag[q.top().second])q.pop();
    40     int x=q.top().second;ans+=a[x];q.pop();
    41     a[x]=a[pre[x]]+a[nxt[x]]-a[x];
    42     del(pre[x]),del(nxt[x]);
    43     q.push(make_pair(a[x],x));
    44 }
    45 int main()
    46 {
    47     n=read(),m=read();
    48     for (int i=1;i<=n;i++)a[i]=read();
    49     for (int i=1;i<=n-1;i++)a[i]=a[i+1]-a[i];
    50     n--;a[0]=a[n+1]=inf;
    51     for (int i=1;i<=n;i++)pre[i]=i-1;
    52     for (int i=1;i<=n;i++)nxt[i]=i+1;
    53     for (int i=1;i<=n;i++)
    54         q.push(make_pair(a[i],i));
    55     for (int i=1;i<=m;i++)solve();
    56     printf("%lld
    ",ans);
    57 }
  • 相关阅读:
    10.13 新版本go on~
    9.30 总结一下九月呗
    9.25 学习下日期加减
    9.22 迎难而上不要怂!
    9.22 Sans-serif VS Serif
    9.22 keep studying
    【LeetCode刷题】最长同值路径:妙解
    【LeetCode刷题】机器人走路最大距离:妙解
    【LeetCode刷题】不使用+-的加减法:妙解
    【LeetCode刷题】NIM游戏:妙解
  • 原文地址:https://www.cnblogs.com/fengzhiyuan/p/8486606.html
Copyright © 2020-2023  润新知