题意:
解法:
题意其实就是n个数取出最多m个,满足取出的不相邻,求最大值.
如果第1个数选择a[i],那么a[i-1]和a[i+1]不能取.
当要取第2个数时,要么取除了a[i-1],a[i],a[i+1]外的数,
要么讲a[i]改成取a[i-1]和a[i+1]这两个数.
取其中的max,那么其实我们可以这样做,
取出a[i]的时候,在丢入一个a[i-1]+a[i+1]-a[i],
和其他数一起放在堆中,然后堆顶就是下一步要取的位置.
如果我们把a[i]换成了a[i-1]和a[i+1],
那么要加入的就是a[i-2]+a[i]+a[i+2]-(a[i-1]-a[i+1]).
发现每次都需要当前数左边和右边的数的下标,
用l[i]和r[i]做一个双向链表存当前数左边和右边的第一个未取数即可.
code:
#include <bits/stdc++.h>
#define int long long
#define PI pair<int,int>
using namespace std;
const int maxm=2e6+5;
int mark[maxm];
int a[maxm];
int l[maxm];
int r[maxm];
int n,m;
signed main(){
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
l[i]=i-1;
r[i]=i+1;
}
priority_queue<PI,vector<PI>,less<PI> >q;
for(int i=1;i<=n;i++){
q.push({
a[i],i});
}
int ans=0;
while(m--){
PI x=q.top();q.pop();
while(mark[x.second]){
x=q.top();q.pop();
}
if(x.first<0)break;
ans+=x.first;
int p=x.second;
mark[l[p]]=mark[r[p]]=1;
a[p]=a[l[p]]+a[r[p]]-a[p];
q.push({
a[p],p});
//
l[p]=l[l[p]];
r[p]=r[r[p]];
r[l[p]]=p;
l[r[p]]=p;
//
}
cout<<ans<<endl;
return 0;
}