牛客练习赛47-C-DongDong跳一跳

27 篇文章 0 订阅
12 篇文章 0 订阅

链接:https://ac.nowcoder.com/acm/contest/904/C
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述

DongDong有一只超可爱的英短喜欢跳一跳,但此跳一跳非彼跳一跳

有n根柱子,每根柱子都有一个高度和柱子上面鱼干的数量,英短开始的时候可以选择站在任意一根柱子上,每次跳跃不限长度而且只能从左向右跳跃,但只能跳到高度与当前所站高度差绝对值小于等于m的柱子上,英短可贪心了,想吃最多的鱼干,请你设计一个程序能让英短吃到最多的鱼干(最终不一定要落在第n根柱子上)。

输入描述:

第一行给定两个整数,n,m

接下来n行,每行x,y表示这根柱子高度为x,上面有y根鱼干

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

输出描述:

输出英短最多可以吃到多少鱼干

示例1

输入

复制

4 4
1 0
2 100
100 5
6 10

输出

复制

110

地址:https://ac.nowcoder.com/acm/contest/904/C

思路:思维+线段树

由于x<=1e6较小,因此考虑能否从后推前,d[i]表示高度为i时能够得到的最大价值,每次维护d[xi-m]到d[xi+m]的最大值,而取第i个时,ax=max{d[xi-m],d[xi+m]}, ans=max(ans,ax+yi), 然后 更新 d[xi] = ax+yi; 而这可以用线段树来维护。

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;

const int MAX_N=1e6+555;
struct tree{
	int l,r;
	LL x;
	int mid(){
		return (l+r)>>1;
	}
};
int n,m;
int a[MAX_N],w[MAX_N];
tree Tree[MAX_N<<2];

void PushUp(int rt);
void Build(int l,int r,int rt);
void Update(int t,LL x,int rt);
LL Query(int l,int r,int rt);
int main()
{
	scanf("%d%d",&n,&m);
	Build(1,MAX_N-5,1);
	for(int i=1;i<=n;++i)
		scanf("%d%d",&a[i],&w[i]);
	LL ans=0,ax;
	int l,r;
	for(int i=1;i<=n;++i)
	{
		l=max(0,a[i]-m);	r=a[i]+m;
		ax=Query(l,r,1);
		Update(a[i],ax+w[i],1);
		ans=max(ans,ax+w[i]);
	}
	printf("%lld\n",ans);

	return 0;
}

void PushUp(int rt)
{
	Tree[rt].x=max(Tree[rt<<1].x,Tree[rt<<1|1].x);
}

void Build(int l,int r,int rt)
{
	Tree[rt].l=l;	Tree[rt].r=r;
	Tree[rt].x=0;
	if(l==r){
		return;
	}
	int h=(l+r)>>1;
	Build(l,h,rt<<1);
	Build(h+1,r,rt<<1|1);
	PushUp(rt);
}

void Update(int t,LL x,int rt)
{
	if(Tree[rt].l==Tree[rt].r){
		Tree[rt].x=x;
		return;
	}
	int h=Tree[rt].mid();
	if(t<=h){
		Update(t,x,rt<<1);
	}else	Update(t,x,rt<<1|1);
	PushUp(rt);
}

LL Query(int l,int r,int rt)
{
	if(l<=Tree[rt].l&&r>=Tree[rt].r){
		return Tree[rt].x;
	}
	int h=Tree[rt].mid();
	LL res=0;
	if(h>=l)	res=max(res,Query(l,r,rt<<1));
	if(h+1<=r)	res=max(res,Query(l,r,rt<<1|1));
	return res;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值