[优先队列] 洛谷 P1484 种树

题目描述

cyrcyr今天在种树,他在一条直线上挖了n个坑。这n个坑都可以种树,但为了保证每一棵树都有充足的养料,cyrcyr不会在相邻的两个坑中种树。而且由于cyrcyr的树种不够,他至多会种k棵树。假设cyrcyr有某种神能力,能预知自己在某个坑种树的获利会是多少(可能为负),请你帮助他计算出他的最大获利。

输入输出格式

输入格式:

第一行,两个正整数n,k。

第二行,n个正整数,第i个数表示在直线上从左往右数第i个坑种树的获利。

输出格式:

输出1个数,表示cyrcyr种树的最大获利。

输入输出样例

输入样例#1:
6 3 
100 1 -1 100 1 -1
输出样例#1:
200

说明

对于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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/10328154.html
今日推荐