链接
题目描述
给出n个木桩,每个木桩有高度和收益,一个木桩只能向右跳,并且只能跳到高度差的绝对值为m的柱子,问最大收益是多少
样例输入
4 4
1 0
2 100
100 5
6 10
样例输出
110
思路
设
f
i
f_i
fi表示高度为i的时候的最大收益,那么肯定在高度范围内找一个最大值去更新当前高度
找最大值这个过程可以用线段树优化
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
ll ans;
int n, m;
ll tr[4000005], h[200005], a[200005], f[1000005];
void change(int x, int l, int r, int L, int R, ll w)
{
if(l == r)
{
tr[x] = max(w, tr[x]);
return;
}
int mid = (l + r) >> 1;
if(L <= mid) change(x * 2, l, mid, L, R, w);
if(mid < R) change(x * 2 + 1, mid + 1, r, L, R, w);
tr[x] = max(tr[x * 2], tr[x * 2 + 1]);
}
ll ask(int x, int l, int r, int L, int R)
{
if(L <= l && r <= R)
return tr[x];
ll p = 0;
int mid = (l + r) >> 1;
if(L <= mid) p = max(p, ask(x * 2, l, mid, L, R));
if(mid < R) p = max(p, ask(x * 2 + 1, mid + 1, r, L, R));
return p;
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d%d", &h[i], &a[i]);
for(int i = 1; i <= n; ++i) {
f[h[i]] = max(f[h[i]], ask(1, 1, 1000000, max(h[i] - m, (ll)0), min(h[i] + m, (ll)1000000)) + a[i]);
change(1, 1, 1000000, h[i], h[i], f[h[i]]);
ans = max(ans, f[h[i]]);
}
printf("%lld", ans);
return 0;
}