Luogu 3620 数据备份 - Set

Solution

很显然, 最优情况肯定是相邻两个相连 。

然后模型就跟 Luogu1484 类似了。

把两个房子 看成一个坑 (参考 Luogu1484), 选取 $k$ 个不相邻的坑, 使得权值最小。

Luogu1484 则是 选取 至多 $k$ 个不相邻坑,  使得权值最大。

先考虑简单问题:

当$k= 1$时, 肯定是选择 最大 的$a[i]$ 

当$k= 2$时, 仅有两种情况  选 最大的 $a[i]$ 和 不相邻的 $a[j]$ 或者 $a[i+1]+a[i-1]$

   我们先选了最大的$a[i]$

   那么怎么样才能让下一个找到的最大的 $a[j]$ 是满足条件的解呢?

  我们把 $a[i - 1]$ 和 $a[i + 1]$ 删去, 然后把 $a[i]$改为 $a[i + 1] + a[i - 1] - a[i]$,这样就满足了肯定不会 单独选到 $a[i + 1]或a[i-1]$。

  并且我们若想要选$a[i+1]和a[i-1]$且不选$a[i]$ 只需要再选一次$a[i]$即可。

在$k$更大的情况下同样适用。

然后就用链表存储 $nxt$ 与 $pre$, $Set$ 维护 最大值/ 最小值。

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<set>
 5 #define rd read()
 6 #define ll long long
 7 using namespace std;
 8 typedef pair<ll, int> P;
 9 
10 const int N = 1e5 + 5;
11 const ll inf = 1e10;
12 
13 int n, k;
14 int nxt[N], pre[N];
15 ll a[N], ans;
16 set<P> st;
17 
18 int read() {
19     int X = 0, p = 1; char c = getchar();
20     for (; c > '9' || c < '0'; c = getchar())
21         if (c == '-') p = -1;
22     for (; c >= '0' && c <= '9'; c = getchar())
23         X = X * 10 + c - '0';
24     return X * p;
25 }
26 
27 void del(int x) {
28     nxt[pre[x]] = nxt[x];
29     pre[nxt[x]] = pre[x];
30 }
31 
32 int main()
33 {
34     n = rd; k = rd;
35     for (int i = 1; i <= n; ++i) 
36         a[i] = rd;
37     n--;
38     for (int i = 1; i <= n; ++i)
39         a[i] = a[i + 1] - a[i];
40     for (int i = 1; i <= n; ++i)
41         nxt[i] = i + 1, pre[i] = i - 1;
42     for (int i = 1; i <= n; ++i)
43         st.insert(P(a[i], i));
44     a[0] = a[n + 1] = inf;
45     set<P> :: iterator it;
46     for (; k; --k) {
47         it = st.begin();
48         P tp = *it;
49         int x = tp.second; ll y = a[x];
50         ll t = a[pre[x]] + a[nxt[x]] - y;
51         a[x] = t; ans += y;
52         st.insert(P(t, x));
53         st.erase(P(y, x));
54         if (pre[x])
55             st.erase(P(a[pre[x]], pre[x])), del(pre[x]);
56         if (nxt[x] && nxt[x] != n + 1)
57             st.erase(P(a[nxt[x]], nxt[x])), del(nxt[x]);
58     }
59     printf("%lld\n", ans);
60 }
View Code

猜你喜欢

转载自www.cnblogs.com/cychester/p/9703408.html
今日推荐