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

正题

      第五题:种树

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

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

      我们把多步拆成多个一步来求解,当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);
}


阅读更多
版权声明: https://blog.csdn.net/Deep_Kevin/article/details/79958449
上一篇最小函数值,洛谷之提高历练地,堆
下一篇树状数组(改点求段) ,洛谷之提高历练地,提高模板-nlogn数据结构
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭