1. 程式人生 > 其它 >cf360 B. Levko and Array(二分答案,dp判斷)

cf360 B. Levko and Array(二分答案,dp判斷)

題意:

修改陣列中的不超過k個數,最小化相鄰數之差的絕對值的最大值。

k <= n <= 2000

思路:

\(f(i)\) 表示第 \(i\) 個數不變,前 \(i\) 個數合法,至少要改變幾個數。

初始化 \(f(i)=i-1\) 表示前面的數都改變。列舉 \(i\) 之前的所有 \(j\),把 \([j+1,i-1]\) 都改變,改成單調增或者單調減,那麼 \(|a_i-a_j|/(i-j)\le ans\) 時ans合法。

對於每個 \(f(i)\),當 \(f(i)+n-i\le k\) 時有答案。即後面的數都改變。

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2010;
int n, k, a[N], f[N];

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

signed main()
{
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);

    ll l = 0, r = 2e9;
    while(l < r) {
        ll mid = l + r >> 1; //注意開ll
        if(pd(mid)) r = mid; else l = mid + 1;
    }

    printf("%lld", l);

    return 0;
}