51nodP1380 夹克老爷的逢三抽一
此题的核心在于如何实现反悔操作.
我们可以在选出当前最优并删去左右节点后,在当前最优的节点处再次添加一个\(a[r[i]]+a[l[i]]-a[i]\)的点,如果再次选这个点就意味着一次反悔.
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define il inline
#define rg register
#define pli pair<ll, int>
using namespace std;
typedef long long ll;
const int O = 1e5 + 10;
template<class TT>
il TT read() {
TT o = 0,fl = 1; char ch = getchar();
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') fl = -1, ch = getchar();
while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
return fl * o;
}
ll ans, a[O];
set<pli >s;
int n, lst[O], nxt[O];
il void Delete(int u) {
s.erase(pli(-a[u], u));
lst[nxt[u]] = lst[u];
nxt[lst[u]] = nxt[u];
}
int main() {
n = read<int>();
for (int i = 1; i <= n; ++i) {
a[i] = read<ll>();
lst[i % n + 1] = i;
nxt[i] = i % n + 1;
s.insert(pli(-a[i], i));
}
n /= 3;
for (int i = 1; i <= n; ++i) {
int u = s.begin()->second;
ll y = a[lst[u]] + a[nxt[u]];
Delete(lst[u]); Delete(nxt[u]);
ans += a[u];
s.erase(pli(-a[u], u));
a[u] = y - a[u];
s.insert(pli(-a[u], u));
}
printf("%lld\n", ans);
return 0;
}