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
  • 相关阅读:
    第二十九课 循环链表的实现
    第二十八课 再论智能指针(下)
    第二十七课 再论智能指针(上)
    第二十六课 典型问题分析(Bugfix)
    普通new和placement new的重载
    leetcode 581. Shortest Unsorted Continuous Subarray
    leetcode 605. Can Place Flowers
    leetcode 219. Contains Duplicate II
    leetcode 283. Move Zeroes
    leetcode 217. Contains Duplicate
  • 原文地址:https://www.cnblogs.com/BIGTOM/p/8992224.html
Copyright © 2011-2022 走看看