Codeforces 361D Levko and Array【二分+dp】好题!

142 篇文章 0 订阅

B. Levko and Array
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Levko has an array that consists of integers: a1, a2, ... , an. But he doesn’t like this array at all.

Levko thinks that the beauty of the array a directly depends on valuec(a), which can be calculated by the formula:

The less value c(a) is, the more beautiful the array is.

It’s time to change the world and Levko is going to change his array for the better. To be exact, Levko wants to change the values of at mostk array elements (it is allowed to replace the values by any integers). Of course, the changes should make the array as beautiful as possible.

Help Levko and calculate what minimum number c(a) he can reach.

Input

The first line contains two integers n andk (1 ≤ k ≤ n ≤ 2000). The second line contains space-separated integersa1, a2, ... , an ( - 109 ≤ ai ≤ 109).

Output

A single number — the minimum value of c(a) Levko can get.

Examples
Input
5 2
4 7 4 7 4
Output
0
Input
3 1
-100 0 100
Output
100
Input
6 3
1 2 3 7 8 9
Output
1
Note

In the first sample Levko can change the second and fourth elements and get array:4, 4, 4, 4, 4.

In the third sample he can get array: 1, 2, 3, 4, 5, 6.


题目大意:

最多可以修改K次数字,每次修改一个数字变成任意值,C=max(a【i+1】-a【i】);求操作之后最小的C.


思路:


1、思路来源于巨牛:http://www.cnblogs.com/DreamHighWithMe/p/3455723.html


2、我们二分C的值,然后通过处理最小改动次数,来判断当前二分中间值mid是否可行,如果可行,记录可行解,否则继续二分。


3、处理最小改动次数,考虑dp,设定dp【i】表示a【i】不进行改动,且前i个满足mid值的限定的最少改动次数。

那么不难推出其状态转移方程:
dp【i】=dp【j】+i-j-1;(表示从j到i开区间内的数据全部进行改动);那么改动的前提呢?(a【i】-a【j】<=(i-j)*mid);表示我们从a【j】到a【i】中间的数都平均开分配值,假设a【j】=1;a【i】=10,此时mid的值为2,如果从i到j中间有4个数,那么我们最好的分配方案就是:

a【j】=1;a【j+1】=3;a【j+2】=5;a【j+3】=7;a【j+4】=9;a【i】=10;将差值平均开来是最优的分配方案。


4、dp过程中,注意一些小的细节,具体参考代码。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll __int64
ll dp[2005];
ll a[2005];
ll n,k;
ll Dp_Slove(ll mid)
{
    memset(dp,0x3f3f3f3f,sizeof(dp));
    dp[1]=0;
    for(ll i=2;i<=n;i++)
    {
        dp[i]=i-1;
        for(ll j=i-1;j>=1;j--)
        {
            if(abs(a[i]-a[j])<=mid*(i-j))
            {
                dp[i]=min(dp[i],dp[j]+i-j-1);
            }
        }
        if(dp[i]+n-i<=k)return 1;
    }
    if(dp[n]<=k)return 1;
    else return 0;
}
int main()
{
    while(~scanf("%I64d%I64d",&n,&k))
    {
        for(ll i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
        }
        ll l=0,r=2000000050;
        ll ans=0;
        while(r>=l)
        {
            ll mid=(l+r)/2;
            if(Dp_Slove(mid))
            {
                r=mid-1;
                ans=mid;
            }
            else l=mid+1;
        }
        printf("%I64d\n",ans);
    }
}







评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值