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;
}

猜你喜欢

转载自www.cnblogs.com/lylyl/p/11695775.html
今日推荐