『二分答案·DP』Levko and Array

该博客探讨了一道关于寻找相邻元素差的最大值最小化的题目,提出通过二分答案结合动态规划(DP)的方法来解决。博主详细解释了如何利用DP状态转移方程,并阐述了时间复杂度为O(n^2*logW)的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

在这里插入图片描述即最小化相邻元素差的最大值。

题解

我们发现修改哪些数很难查找,显然需要二分答案这个最大值。

我们需要保证相邻两个元素的差都小于这个二分答案的数值,因此我们可以采用DP解决。

我们设f[i]f[i]f[i]表示一定保留第i个数字的情况下,最多能够保留多少个数字。

可以得到:f[i]=max(f[j])+1,∣a[i]−a[j]∣≤mid∗(i−j)f[i]=max(f[j])+1,|a[i]-a[j]|\leq mid*(i-j)f[i]=max(f[j])+1,a[i]a[j]mid(ij)

只要有一个f[i]是大于等于n-k的,表明有一种方案是合法的,则判断当前check函数为真。

时间复杂度:O(n2logW)O(n^2log W)O(n2logW)

代码如下:

#include <bits/stdc++.h>

#define int long long

using namespace std;
const int N = 3000;

int n, k;
int a[N], f[N];

bool check(int x)
{
	for (int i=1;i<=n;++i)
	{
		f[i] = 1;
		for (int j=1;j<i;++j)
		    if (abs(a[i]-a[j]) <= (i-j)*x)
		        f[i] = max(f[j]+1,f[i]);
		if (f[i] >= n-k) return 1;
	}
	return 0;
}

signed main(void)
{
	scanf("%lld %lld", &n, &k);
	for (int i=1;i<=n;++i)
		scanf("%lld", a+i);
	int l = 0, r = 1e16, mid;
	while (l+1 < r)
	{
		mid = l+r >> 1;
		check(mid) ? r = mid : l = mid;
	} 
	printf("%lld\n", check(l) ? l : r);
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值