两个做法WQS二分,或者后悔贪心,这里选择后悔贪心+双向链表。
容易发现如果拿了一个,或者要不拿这个而去拿左右两边的。
答案为 (a_{nxt_i} + a_{pre_i} - a_i) 然后直接贪心。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
const ll MAXN = 1e6+10;
priority_queue <pll> q;
ll N, M, val[MAXN], nxt[MAXN], ans, pre[MAXN], vis[MAXN];
void del(ll);
int main() {
scanf("%lld%lld", &N, &M);
if (N == 1 && M == 1) {
scanf("%lld", &ans);
printf("%lld
", ans);
return 0;
}
if (N / 2 < M) {
puts("Error!");
return 0;
}
for (ll i = 1; i <= N; i++)
scanf("%lld", val+i);
for (ll i = 1; i <= N; i++)
pre[i] = i-1, nxt[i] = i+1, q.push(make_pair(val[i], i)); pre[1] = N, nxt[N] = 1;
for (ll i = 1; i <= M; i++) {
while (vis[q.top().second]) q.pop();
ll now = q.top().second; q.pop();
ans += val[now];
val[now] = val[pre[now]] + val[nxt[now]] - val[now];
del(pre[now]); del(nxt[now]);
q.push(make_pair(val[now], now));
}
printf("%lld
", ans);
return 0;
}
void del(ll pos) {
vis[pos] = 1;
ll l = pre[pos], r = nxt[pos];
pre[pos] = nxt[pos] = 0;
nxt[l] = r, pre[r] = l;
}