种树,洛谷之提高历练地,堆

正题

      第五题:种树

      这题看上去很烦,实际上也很烦。。。

      那么我们第一个想到的就是用堆维护最大值。

      我们把多步拆成多个一步来求解,当k=1的时候,那么答案就是最大值。

      当k=2时,要么就是多选一个不相邻的,要么就是同时选相邻的,为什么旁边两个要么同时选要么同时不选呢?可能存在选其中一个再选与其不相邻的一个吗?很明显是不可能的,因为当前选出来的已经是最大的了,所以让旁边的去选另外一个倒不如让最大的去累加。

      我们就照这样推下去,就会发现每次种下一棵树,就不能重复种了,当它当前的距离最近的左边空地和距离最近的右边空地还是可以种树的,那么我们就用一个tf数组来维护这个东西。

      以上是用来解释大神ZZY的博客的,,,大佬博客传送门

代码<不要说我抄。。逃>

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;

int n,k;
int s[500010];
bool tf[500010];
struct node{
	int x,d;
	bool operator<(const node y)const{
		return d<y.d;
	}
};
priority_queue<node> f;
long long ans=0;
int left[500010],right[500010];

int main(){
	scanf("%d %d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%d",&s[i]);
		f.push((node){i,s[i]});
		left[i]=i-1;right[i]=i+1;
	}
	memset(tf,false,sizeof(tf));
	left[n+1]=n;right[0]=1;
	while(k--){
		while(tf[f.top().x]==true) f.pop();
		node now=f.top();
		f.pop();
		if(now.d<0) break;
		ans+=now.d;
		tf[left[now.x]]=tf[right[now.x]]=true;
		s[now.x]=s[left[now.x]]+s[right[now.x]]-s[now.x];
		now.d=s[now.x];
		left[now.x]=left[left[now.x]];
		right[now.x]=right[right[now.x]];
		left[right[now.x]]=now.x;
		right[left[now.x]]=now.x;
		f.push(now);
	}
	printf("%lld",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值