【DP】【线段树优化】Day3 - C

11 篇文章 0 订阅

链接

C

题目描述

给出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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值