二分答案加DP判断

来源:互联网 发布:mui登录模板源码 编辑:程序博客网 时间:2024/05/28 01:36
题意:给定数列{an},任意改动其中至多k项,求相邻两项差的绝对值的最大值的最小值。
思路:二分答案(二分的区间可以优化),对于某一个二分值mid,采用DP检验其可行性。
设dp[i]表示考虑前i个数,且第i个数不变,至少需要改多少个才能使得答案不大于mid。
那么考虑下一个不变的数是a[j],则a[i+1]~a[j-1]这些数可以任意改变,前提是abs(a[i]-a[j])<=(j-i)*mid。

接下来枚举最后一个不变的数到底是哪个,ans=min(ans,dp[i]+n-i)。只要ans<=k就可行,否则不可行

周赛的题目 mark下

#include<cstdio>#include<cmath>#include<algorithm>#include<ctime>#define maxn 500#define inf 3000#define ll long longusing namespace std;ll n,k;ll a[maxn+5];ll dp[maxn+5];bool check(ll mid) {    for(int i=1; i<=n; i++) dp[i]=i-1;    for(int i=1; i<=n; i++) {        for(int j=i+1; j<=n; j++) {            if(abs(a[j]-a[i])<=(j-i)*mid) {                dp[j]=min(dp[j],dp[i]+(j-i-1));            }        }    }    ll ans=inf;    for(int i=1; i<=n; i++) {        ans=min(ans,dp[i]+(n-i));    }    return ans<=k;}ll solve() {    ll left=-1,right=2000000000;    while(left+1<right) {        ll mid=(left+right)>>1;        if(check(mid)) {            right=mid;        } else {            left=mid;        }    }    return right;}int main() {    int T;    scanf("%d",&T);    for(int kase=1; kase<=T; kase++) {        scanf("%lld%lld",&n,&k);        for(int i=1; i<=n; i++) {            scanf("%lld",&a[i]);        }        printf("%lld\n",solve());    }    return 0;}

0 0
原创粉丝点击