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

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 2899  Solved: 1172
    [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
     
    思路:首先证明不取全局最小值时一定是把它相邻的两个取了。然后每次取最小值后,向堆中加入v[p -> pre] + v[p -> nex] - v[p],这样如果之后取了这个元素,则等价于取了与p相邻的两个,并把之前取的p悔掉。
    实现时用个堆与链表构成对应关系即可,第一次写得推敲一会。
     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int n, k, d[100015];
    45 struct gg {
    46     int l, r, v, use, index;
    47     gg () {}
    48     gg (int l, int r, int v, int use, int index) : l(l), r(r), v(v), use(use), index(index) {}
    49     bool operator > (const gg &g) const {
    50         return v > g.v;
    51     }
    52 } g[200015];
    53 priority_queue<gg, vector<gg>, greater<gg> > que;
    54 int main() {
    55     scanf("%d%d", &n, &k);
    56     d[0] = -MOD, d[n + 1] = MOD << 1;
    57     for (int i = 1; i <= n; ++i) {
    58         scanf("%d", &d[i]);
    59         g[i].l = i - 1;
    60         g[i].r = i + 1;
    61         g[i].v = d[i] - d[i - 1];
    62         g[i].use = 0;
    63         g[i].index = i;
    64         que.push(g[i]);
    65     }
    66     g[n + 1].l = n, g[n + 1].v = d[n + 1] - d[n], g[n + 1].use = 0, g[n + 1].index = n + 1;
    67     int ans = 0, cnt = 0, cnt_index = n + 1;
    68     while (que.size() && cnt < k) {
    69         gg tg = que.top(); que.pop();
    70         int index = tg.index;
    71         if (g[index].use) continue;
    72         //printf("l = %d, r = %d, v = %d
    ", tg.l, tg.r, tg.v);
    73         int pre = g[index].l, nex = g[index].r;
    74         int new_pre = pre, new_nex = nex;
    75         g[pre].use = g[nex].use = 1;
    76         if (1 != new_pre) {
    77             new_pre = g[new_pre].l;
    78         }
    79         if (n + 1 != new_nex) {
    80             new_nex = g[new_nex].r;
    81         }
    82         ans += tg.v;
    83         ++cnt_index;
    84         g[cnt_index] = gg(new_pre, new_nex, g[pre].v + g[nex].v - tg.v, 0, cnt_index);
    85         que.push(g[cnt_index]);
    86         g[new_pre].r = g[new_nex].l = cnt_index;
    87         ++cnt;
    88     }
    89     printf("%d
    ", ans);
    90     return 0;
    91 }
    View Code
  • 相关阅读:
    Naive Operations HDU6315 (杭电多校2G)
    Baker Vai LightOJ
    LOJ#6278. 数列分块入门 2
    LOJ#6277. 数列分块入门 1
    Picture POJ
    Who Gets the Most Candies? POJ
    Dividing the Path POJ
    Balanced Sequence HDU
    归并排序
    Flying to the Mars
  • 原文地址:https://www.cnblogs.com/BIGTOM/p/8992224.html
Copyright © 2011-2022 走看看