1. 程式人生 > >1150: [CTSC2007]數據備份Backup

1150: [CTSC2007]數據備份Backup

inf wid 如果 online pau ems mit 輸出 一次

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\n", 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\n", ans); 90 return 0; 91 }
View Code

1150: [CTSC2007]數據備份Backup