1150: [CTSC2007]数据备份Backup

1150: [CTSC2007]数据备份Backup

https://lydsy.com/JudgeOnline/problem.php?id=1150

分析:

  堆+贪心。

  每次选最小的并一定是最优的,如果不选这个最小的,那一定是为了取它左右两边(两条都要取才可能比当前优)。

  如果先选了最小的,考虑后面如何撤销。选了这个后,左右两边的线段就要删了,那么在加入一个长度为:左边的长度+右边的长度-当前的线段的长度 的一条线段。

  wqs二分模拟费用流

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18 
19 const int N = 100005;
20 const int INF = 1e9;
21 
22 int pre[N], nxt[N], d[N], a[N];
23 bool vis[N]; 
24 
25 struct Edge{
26     int len, id;
27     Edge() { }
28     Edge(int a, int b) { len = a, id = b; }
29     bool operator < (const Edge &A) const {
30         return len > A.len;
31     }
32 };
33 priority_queue<Edge> q;
34 
35 void del(int i) {
36     vis[i] = 1;
37     nxt[pre[i]] = nxt[i];
38     pre[nxt[i]] = pre[i];
39 }
40 
41 int main() {
42     int n = read(), m = read();
43     for (int i = 1; i <= n; ++i) d[i] = read();
44     for (int i = 1; i < n; ++i) {
45         a[i] = d[i + 1] - d[i];
46         q.push(Edge(a[i], i));
47     }
48     a[0] = a[n] = INF;
49     for (int i = 1; i <= n; ++i) pre[i] = i - 1, nxt[i] = i + 1;
50     int ans = 0;
51     while (m --) {
52         while (vis[q.top().id]) q.pop();
53         Edge now = q.top(); q.pop();
54         ans += now.len;
55         int i = now.id, t;
56         t = min(a[pre[i]] + a[nxt[i]] - now.len, INF);
57         del(pre[i]); del(nxt[i]);
58         a[i] = t; q.push(Edge(a[i], i));
59     }
60     cout << ans;
61     return 0;
62 }
原文地址:https://www.cnblogs.com/mjtcn/p/10050768.html