牛客练习47 DongDong跳一跳 (线段树、思维)

题目:https://ac.nowcoder.com/acm/contest/904/C

题意:给n个柱子,每个柱子有高度值,每个柱子上面有鱼干值,给定一个m值,你一开始可以在从任意一个柱子上开始,每次向右跳,跳到的柱子高度满足 其与之前所在柱子高度差绝对值小于等于m,问最后你最大可以拥有多少鱼干?

数据范围:1<=n<=200000,1<=m<=500,对于每根柱子的x,y,1<=x<=1000000,1<=y<=1000000

题解:考虑一下,只能从左往右跳,如果当前在某个柱子的位置时,一定是之前左边的柱子跳过来的,为了使当前获得鱼干最多,肯定是左边满足高度差的、并且可以获得最多鱼干的柱子。这样,我们遍历这n个柱子,先查询,后更新。

使用线段树,维护的是当前这段高度区间拥有的最大鱼干量,假设当前柱子高度为h,那么先查询区间(max(0,h-m),h+m)的鱼干量,更新的时候加上当前位置的鱼干数。

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#define LL long long
#define MID (l+r)>>1
#define lson step<<1
#define rson step<<1|1 
using namespace std;
const int maxn=1e6+5;
int h[maxn],val[maxn];
LL tree[maxn<<2];
void pushup(int step)
{
	tree[step]=max(tree[lson],tree[rson]);
}
void build(int l,int r,int step)
{
	if(l==r)
	{
		return ;
	}
	int mid=MID;
	build(l,mid,lson);
	build(mid+1,r,rson);
	pushup(step);
}
void update(int l,int r,int pos,LL val,int step)
{
	if(l==r)
	{
		tree[step]=val;
		return ;
	}
	int mid=MID;
	if(pos<=mid)
		update(l,mid,pos,val,lson);
	else
		update(mid+1,r,pos,val,rson);
	pushup(step);
	  
}
LL query(int l,int r,int left,int right,int step)
{
	if(left<=l&&right>=r)
	{
		return tree[step];	
	}	
	int mid=MID;
	LL ans=0;
	if(left<=mid)
		ans=max(ans,query(l,mid,left,right,lson));
	if(right>mid)
		ans=max(ans,query(mid+1,r,left,right,rson));
	return ans;
} 
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>h[i]>>val[i];
	}
	//build(1,1000000,1);
	LL res=0;
	for(int i=1;i<=n;i++)
	{
		int l,r;
		l=max(0,h[i]-m);
		r=h[i]+m;
		//cout << l << ' ' << r << endl;
		LL tem=query(1,1000000,l,r,1);
		//cout << tem << endl;
		update(1,1000000,h[i],val[i]+tem,1);
		res=max(res,val[i]+tem);
	}
	cout << res << endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值