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; }