zoukankan      html  css  js  c++  java
  • BZOJ1150: [CTSC2007]数据备份Backup

    1150: [CTSC2007]数据备份Backup

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2357  Solved: 957
    [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 ≤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

    HINT

    Source

    【题解】

    可以证明一定要选相邻的对。

    先把原数组差分,问题转化成在差分数组中选择k个数,这k个数互不相邻且和最小

    对于差分数组中最小的,要么选这个最小的,要么选他两边的数且两个都要选

    选了最小的,导致相邻两个不能选,而再选两个可能不如相邻两个更优

    相邻两个不能只选一个,如果只选一个,倒不如选这个最小的

    有没有可能三个都不选呢?肯定是不可能的。如果都不选,那么答案里的一个数换成最小的,仍然更优

    有了这个结论,就可以用堆贪心

    优先选最小的num[i],然后加入反悔机制,不选最小的,选他相邻的,

    把num[i -> pre] + num[i -> nxt] - num[i]换到num[i]的地方,并压入堆

    用双向链表维护

    可以证明每次从堆里选一个,就一定使选的个数+1

    怎么证明结论是最优的呢?

    原题是n个数选k个

    每次选一个数,变成n - 3个数选k - 1个(边界虚一个点,正无穷大,因为边界点没法选周围两个点)

    把n-2个数看做地位平等的n-2个数,即使他是合起来的,其实也一个样

    然后有结论,要么选这个最小的,要么选他两边的数且两个都要选,上面证明过

    于是选最小的就可以了

    不太严谨

     1 /**************************************************************
     2     Problem: 1150
     3     User: 33511595
     4     Language: C++
     5     Result: Accepted
     6     Time:672 ms
     7     Memory:95816 kb
     8 ****************************************************************/
     9  
    10 #include <iostream>
    11 #include <cstdio>
    12 #include <cstring>
    13 #include <cstdlib>
    14 #include <queue>
    15 #include <vector>
    16  
    17 inline void read(int &x)
    18 {
    19     char ch = getchar(), c = ch;x = 0;
    20     while(ch < '0' || ch > '9')c = ch, ch = getchar();
    21     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
    22     if(c == '-')x = -x;
    23 }
    24  
    25 const int INF = 0x3f3f3f3f;
    26 const int MAXN = 1000000 + 10;
    27 const int MAXM = 1000000 + 10;
    28  
    29 int n,m,cnt,b[MAXN << 2],ans,num,tmp;
    30  
    31 struct Node
    32 {
    33     int pre,nxt,value,num,cnt;
    34     Node(int _pre, int _nxt, int _value, int _num, int _cnt){pre = _pre, nxt = _nxt, value = _value, num = _num;cnt = _cnt;}
    35     Node(){}
    36 }node[MAXN << 2];
    37  
    38 struct cmp
    39 {
    40     bool operator()(int a, int b)
    41     {
    42         return node[a].value > node[b].value;
    43     }
    44 };
    45  
    46 std::priority_queue<int, std::vector<int>, cmp> q;
    47  
    48 int main()
    49 {
    50     read(n), read(m);
    51     read(tmp);
    52     for(register int i = 2;i <= n;++ i) 
    53     {
    54         read(num);
    55         ++ cnt;
    56         node[cnt] = Node(cnt - 1,cnt + 1,num - tmp,1,cnt);
    57         tmp = num;
    58         q.push(cnt);
    59     }
    60     node[0] = Node(0,1,INF,0,0);++cnt;
    61     node[cnt] = Node(cnt - 1,0,INF,0,cnt);
    62     register int tmp,pre,nxt;
    63     int now = 0;
    64     while(q.size() && now < m)
    65     {
    66         tmp = q.top(), q.pop();
    67         pre = node[tmp].pre, nxt = node[tmp].nxt;
    68         if(b[node[tmp].cnt])continue;
    69         if(now + node[tmp].num > m)continue;
    70         b[node[tmp].cnt] = b[node[pre].cnt] = b[node[nxt].cnt] = 1; 
    71         ans += node[tmp].value;
    72         now += node[tmp].num;
    73         ++cnt;
    74         node[node[pre].pre].nxt = cnt;
    75         node[node[nxt].nxt].pre = cnt;
    76         node[cnt] = Node(node[pre].pre, node[nxt].nxt, node[pre].value + node[nxt].value - node[tmp].value, node[pre].num + node[nxt].num - node[tmp].num, cnt);
    77         q.push(cnt);
    78     }
    79     printf("%d", ans);
    80     return 0;
    81 }
    BZOJ1150
  • 相关阅读:
    不通过App Store,在iOS设备上直接安装应用程序(转)
    Quest Central for DataBase 5.0.1,6.1 (软件+注册)
    微信公众号自定义菜单与关键词自动回复互斥解决
    转载《Spring AOP中pointcut expression表达式解析 及匹配多个条件》
    ssm 动态切换数据源
    spring aop
    微信公众号自动回复
    转载《spring定时任务轮询(spring Task)》
    N 秒打开一个新窗口
    java webservice maven spring Class Not Found Exception解决
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/7471689.html
Copyright © 2011-2022 走看看