CF360B Levko and Array

题目链接:
洛谷
Codeforces

Solution

二分好题。
答案有单调性,首先二分。
现在问题转化成如何判断最少要改几个,使用 dp,设 \(f(i)\) 表示第 \(i\) 个不改,前 \(i\)最多几个不改,转移方程为:

\[f(i)=\max(f(j)+1) \]

这个转移方程成立,当且仅当第 \(i\) 个和第 \(j\) 个可以同时不选,即 \(|a_i-a_j|\le x*(i-j)\and j<i\),表示的是两者之差小于最大差,所以不选的加 \(1\)

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
const int N=2007;
int f[N],a[N],n,k;
bool check(int x)
{
	for(int i=1;i<=n;i++)f[i]=1;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<i;j++)
			if(abs(a[i]-a[j])<=x*(i-j))f[i]=max(f[j]+1,f[i]);
	}
	for(int i=1;i<=n;i++)
		if(i-f[i]+n-i<=k)return 1;//前面最少改的加上后面都改
	return 0;
}
main()
{
	read(n);read(k);
	for(int i=1;i<=n;i++)
		read(a[i]);
	int l=0,r=2e9,ans;
	while(l<=r)
	{
		int mid=l+r>>1;
		if(check(mid))ans=mid,r=mid-1;
		else l=mid+1;
	}
	cout<<ans;
	return 0;
}
posted @ 2022-08-15 19:26  Epoch_L  阅读(21)  评论(0编辑  收藏  举报