版权声明:_ https://blog.csdn.net/lunch__/article/details/82431504
这个题很早之前就出过 但是一直没有去改
其实也不是很难,用双向链表串起来整个环
每次贪心选取权值最大的
把它和它的前驱后继缩成一个点 权值为前驱加后继减去它的
仔细思考一下就是增加了一个反悔操作 用一个大根堆维护就好了
我一开始
用
去搞 发现重载运算符的时候
如果你用来比较的值是相同的话 意思两个编号权值相同
那么就会有一个点被 的去重功能删了
所以以后打重载运算符还是考虑一下另一维相等的情况把…
这样子就是对的了
struct node {
int val, id;
bool operator < (const node &T) const {
if(val == T.val) return id < T.id;
return val > T.val;
}
}a[N];
Codes
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, m, ans, del[N];
int from[N], to[N];
struct node {
int val, id;
bool operator < (const node &T) const {
if(val == T.val) return id < T.id;
return val > T.val;
}
}a[N];
set<node> T;
void find() {
while(del[(*T.begin()).id]) T.erase(T.begin());
node it = *T.begin(); T.erase(it);
int x = it.id; ans += a[x].val;
a[x].val = a[from[x]].val + a[to[x]].val - a[x].val;
del[from[x]] = del[to[x]] = 1;
to[from[from[x]]] = x; from[to[to[x]]] = x;
from[x] = from[from[x]]; to[x] = to[to[x]];
T.insert(a[x]);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("2151.in", "r", stdin);
freopen("2151.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
if(m > n / 2) return puts("Error!"), 0;
for(int i = 1; i <= n; ++ i) {
scanf("%d", &a[i].val);
from[i] = i - 1;
to[i] = i + 1;
a[i].id = i;
T.insert(a[i]);
}
from[1] = n; to[n] = 1;
for(int i = 1; i <= m; ++ i) find();
cout << ans << endl;
return 0;
}