Solution
很显然, 最优情况肯定是相邻两个相连 。
然后模型就跟 类似了。
把两个房子 看成一个坑 (参考 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 #include2 #include 3 #include 4 #include 5 #define rd read() 6 #define ll long long 7 using namespace std; 8 typedef pair 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 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
:: 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 }