1. 程式人生 > 實用技巧 >CF360B Levko and Array(DP+二分答案)

CF360B Levko and Array(DP+二分答案)

題意:

一個長度為n的序列a[i],可以將其中k個數的值任意改變,要求最小化相鄰兩個數絕對值之差的最大值

題解:

 /*
 *author: zlc
 *zucc_acm_lab
 *just do it
 */
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const int inf=1e9;
const int maxn=2e5+100;
inline int
read () {int x=0;int f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;} ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int n,k; int a[2005]; int dp[2005]; //dp[i]表示前i個值中相鄰兩個數絕對值差不超過mid且第i個值不變,最少的改變次數 //只有當a[i]和a[j]的差不超過mid*(i-j)時才有可能通過改變i~j的元素使得合法 //最後存在某個數使得dp[i]+n-k<=k,說明mid值合法 int check (ll mid) { dp[1]=0; for (int i=2;i<=n;i++) { dp[i]=i-1; for (int j=1;j<i;j++) { if (abs(a[i]-a[j])<=(ll)mid*(i-j)) dp[i]
=min(dp[i],dp[j]+i-j-1); } } if (dp[n]<=k) return 1; for (int i=1;i<=n;i++) if (dp[i]+n-i<=k) return 1; return 0; } int main () { ll ans=0; n=read(),k=read(); for (int i=1;i<=n;i++) a[i]=read(); ll l=0,r=2e9; while (l<=r) { ll mid=(l+r)>>1; if (check(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%lld\n",ans); return 0; }