cyrcyr今天在种树,他在一条直线上挖了n个坑。这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树。而且由于cyrcyr的树种不够,他至多会种k棵树。假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利。n<=500000,k<=n/2
6 3
100 1 -1 100 1 -1
200
看到题目第一想法是dp,发现dp数组开不了这么大
看题解,大佬真的太强辣
每次如果a[i]是最大值,那么就不能选a[i - 1]和a[i + 1],则删掉a[i - 1]和a[i + 1],新添一个点为a[i - 1] + a[i + 1] - a[i]相当于反悔选择a[i]而选择a[i - 1]和a[i + 1]将a[i]的影响去掉,不能单选a[i - 1]和a[i + 1]中的一个是因为a[i]权值最大,只有a[i - 1]和a[i + 1]同时选才可能更优,贪心策略。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 500000 + 7;
ll a[maxn], l[maxn], r[maxn];
struct node {
ll v;
int id;
bool operator <(node b) const {
return v < b.v;
}
} t;
bool flag[maxn];
priority_queue<node> q;
int main()
{
int n, k;
cin >> n >> k;
for(int i = 1; i <= n; i++) {
cin >> t.v;
a[i] = t.v;
l[i] = i - 1;
r[i] = i + 1;
t.id = i;
q.push(t);
}
r[0] = 1;
l[n] = n + 1;
ll ans = 0;
while(k--) {
while(flag[q.top().id]) q.pop();
t = q.top();
if(t.v < 0) break;
q.pop();
ans = ans + t.v;
ll x = t.id;
flag[l[x]] = flag[r[x]] = 1;
a[x] = a[l[x]] + a[r[x]] - a[x];
t.v = a[x];
t.id = x;
l[x] = l[l[x]];
r[x] = r[r[x]];
r[l[x]] = x;
l[r[x]] = x;
q.push(t);
}
cout << ans << endl;
}