CodeForces 394 D. Physical Education and Buns(双二分)

D. Physical Education and Buns

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The Physical education teacher at SESC is a sort of mathematician too. His most favorite topic in mathematics is progressions. That is why the teacher wants the students lined up in non-decreasing height form an arithmetic progression.

To achieve the goal, the gym teacher ordered a lot of magical buns from the dining room. The magic buns come in two types: when a student eats one magic bun of the first type, his height increases by one, when the student eats one magical bun of the second type, his height decreases by one. The physical education teacher, as expected, cares about the health of his students, so he does not want them to eat a lot of buns. More precisely, he wants the maximum number of buns eaten by some student to be minimum.

Help the teacher, get the maximum number of buns that some pupils will have to eat to achieve the goal of the teacher. Also, get one of the possible ways for achieving the objective, namely, the height of the lowest student in the end and the step of the resulting progression.

Input

The single line contains integer n (2 ≤ n ≤ 103) — the number of students. The second line contains n space-separated integers — the heights of all students. The height of one student is an integer which absolute value doesn't exceed 104.

Output

In the first line print the maximum number of buns eaten by some student to achieve the teacher's aim. In the second line, print two space-separated integers — the height of the lowest student in the end and the step of the progression. Please, pay attention that the step should be non-negative.

If there are multiple possible answers, you can print any of them.

Examples

input

Copy

5
-3 -4 -2 -3 3

output

Copy

2
-3 1

input

Copy

5
2 -3 -1 -4 3

output

Copy

1
-4 2

Note

Lets look at the first sample. We can proceed in the following manner:

  • don't feed the 1-st student, his height will stay equal to -3;
  • give two buns of the first type to the 2-nd student, his height become equal to -2;
  • give two buns of the first type to the 3-rd student, his height become equal to 0;
  • give two buns of the first type to the 4-th student, his height become equal to -1;
  • give two buns of the second type to the 5-th student, his height become equal to 1.

To sum it up, when the students line up in non-decreasing height it will be an arithmetic progression: -3, -2, -1, 0, 1. The height of the lowest student is equal to -3, the step of the progression is equal to 1. The maximum number of buns eaten by one student is equal to 2.

题意:给你一个包含n个数的序列,现在要给每个数变化一下,设第i个数变化差为Di,使得变化后原序列可以按某种顺序摆成等差数列。

你现在要使最大的Di最小,输出答案及最终等差序列的首项和公差。

思路:很容易想到先把序列排序,再二分答案和公差,但是首项我居然当时不知道怎么办。。。石乐志。。。

首项不需要枚举也不需要二分,因为我们二分答案为m后,首项的范围为a[0]-m~a[0]+m,对之后的a[1]~a[n-1],按照公差和m计算出它们的最小上界和最大下界,看是否被区间[a[0]-m,a[0]+m]包含即可。如果存在,那么首项可以取所有数计算出的最大下界到最小上界区间中的任意一个数。

注意二分答案的时候为0的情况,r要先+1,不然会WA on test 22(不要问我怎么知道的,我也不知道)

代码:

#include<iostream>
#include<cmath>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<string>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const double pi=acos(-1.0);
const int maxn=200010;
const ll mo=9901;
ll n,m,k;
ll ans,tmp,cnt,ansd,ans1;
ll c[maxn],a[maxn];
ll jud2(ll d,ll m,ll &ans1,ll &ansd)
{
    ll up=a[0]+m,down=a[0]-m;
    for(int i=1;i<n;i++)
    {
        ll xia=a[i]-m-i*d;
        ll shang=a[i]+m-i*d;
        if(xia>up) return 1;
        else if(shang<down) return 2;
        up=min(up,shang);
        down=max(down,xia);
    }
    ans1=down;
    ansd=d;
    return 0;
}
ll jud1(ll m,ll &ans1,ll &ansd)
{
    ll l=0,r=a[1]+m-(a[0]-m);
    ll ans=r;
    while(l<r)
    {
        ll mid=(l+r)>>1;
        ll k=jud2(mid,m,ans1,ansd);
        if(k==1) l=mid+1;
        else if(k==2) r=mid;
        else return 1;
    }
    return !jud2(r,m,ans1,ansd);
}
int main()
{
    int T,cas=1;
    while(scanf("%lld",&n)!=EOF)
    {
        for(int i=0;i<n;i++)
        scanf("%lld",&a[i]);
        sort(a,a+n);
        ll l=0,r=a[n-1]-a[0]+1;
        while(l<r)
        {
            ll mid=(l+r)>>1;
            if(jud1(mid,ans1,ansd)) {r=mid;}
            else l=mid+1;
        }
        //if(ansd==0) ans1=a[0];
        printf("%lld\n%lld %lld\n",r,ans1,ansd);
    }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值