题目描述
cyrcyr今天在种树,他在一条直线上挖了n个坑。这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树。而且由于cyrcyr的树种不够,他至多会种k棵树。假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利。
输入输出格式
输入格式:
第一行,两个正整数n,k。
第二行,n个正整数,第i个数表示在直线上从左往右数第i个坑种树的获利。
输出格式:
输出1个数,表示cyrcyr种树的最大获利。
输入输出样例
说明
对于20%的数据,n<=20。
对于50%的数据,n<=6000。
对于100%的数据,n<=500000,k<=n/2,在一个地方种树获利的绝对值在1000000以内。
题解
- 对于一个点,我们可以记录一下它的左边l和它的右边r
- 若当前i被选了,我们可以把a[i]的值赋值为a[l[i]]+a[r[i]]-a[i](要不一起选要不就一起不选),然后将左边右边的对应该一下就行了
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <queue> 4 #include <vector> 5 #define ll long long 6 #define N 500010 7 using namespace std; 8 struct node 9 { 10 ll v;int d; 11 bool operator <(const node &a)const {return v<a.v;} 12 }p; 13 priority_queue<node>Q; 14 ll a[N],ans; 15 int l[N],r[N],vis[N],n,k; 16 int main() 17 { 18 scanf("%d%d",&n,&k),r[0]=1,l[n+1]=n; 19 for (int i=1;i<=n;i++) scanf("%lld",&a[i]),l[i]=i-1,r[i]=i+1,Q.push((node){a[i],i}); 20 while (k--) 21 { 22 while (vis[Q.top().d]) Q.pop(); 23 p=Q.top(),Q.pop(); 24 if (p.v<0) break; 25 ans+=p.v,a[p.d]=a[l[p.d]]+a[r[p.d]]-a[p.d],p.v=a[p.d],vis[l[p.d]]=vis[r[p.d]]=1, 26 l[p.d]=l[l[p.d]],r[p.d]=r[r[p.d]],r[l[p.d]]=p.d,l[r[p.d]]=p.d,Q.push((node){p.v,p.d}); 27 } 28 printf("%lld",ans); 29 }