题目: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;
}