算法

二分-2020-05-09

2020-05-09  本文已影响0人  _NewMoon

记录今天做的两道二分题

1.牛牛的揠苗助长

题目链接:https://ac.nowcoder.com/acm/contest/5531/C
题目
牛牛有一块长度大小为n的菜园,他首先对这块菜园从1到n进行了编号,每一块地分别为1号、2号...n号菜地,然后他往每块菜地中都种下了一些水稻,一开始,第i块菜地中的水稻高度均为a[i]个单位。然后我们知道水稻的生长周期都是n天,也就是说每逢n天水稻就会长高一个单位。但是不巧的是整个菜园中每一块菜地的生长周期都错开了,具体来说,第1天的时候第1块菜地中的水稻长高一个单位,第2天的时候第2块菜地中的水稻长高一个单位....第n天的时候第n块菜地中的水稻长高一个单位,接下来第n+1天,又轮到第1块菜地中的水稻长高一个单位以此类推。

每天在水稻进行自然生长之后,牛牛可以施展他神奇的魔法,这个魔法可以让任意一块菜地中的水稻长高一个单位,或者让任意一块菜地中的水稻缩短一个单位,当然啦,他也可以不进行任何操作。

牛牛看到菜园中的水稻参差不齐十分难受,请问至少在第几天,他能够让所有的水稻都长到同一个高度?

输入

第一行是一个正整数n,(1≤n≤10^5),表示有菜园有n块菜地。
接下来一行输入n个正整数,表示每块菜地上水稻的高度,水稻的高度1≤a[i]≤10^9。
保证一开始输入时水稻的高度不全都相同(数据保证答案至少为1)。

中位数的一个性质,如果一个数列中的数全部放到数轴上,那么到这些数距离之和最小的数是中位数。
从题意来看,如果天数给得足够大,我们肯定可以使所有水稻高度一致,所以我们可以二分天数,在check函数中,我们可以先让这些水稻自然生长,然后对这些水稻进行操作使其高度全部相同(这里,将标准设置为数列的中位数,高于中位数的,缩短它,低于中位数的,长高),如果操作数小于天数,则返回true

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
typedef long long LL;
const int N = 1e5+100;

int n;
LL a[N],b[N];

bool check(LL d){
   //d天,先自然生长,然后操作,使水稻高度全部一致的操作次数如果小于等于d,说明d天满足条件
    for(int i = 1; i<=n; i++){
        b[i] = a[i] + (d%n>=i);
    }
    sort(b+1,b+1+n);
    //在一个数列(放在数轴中)中,中位数距离所有点的距离之和最小
    LL ans = 0;
    LL mid = b[(n+1)/2];
    for(int i = 1; i<=n; i++) ans += abs(b[i] - mid);
    return ans <= d;
}
int main()
{
    scanf("%d",&n);
    
    for(int i = 1; i<=n; i++) scanf("%d",&a[i]);
    
    LL l = 0, r = 1e15;
    while(l<r){
        LL mid = (l+r)>>1;
        if(check(mid)) r = mid;
        else l = mid+1;
    }
    printf("%lld\n",l);
    return 0;
}

J.签到题

题目链接:https://ac.nowcoder.com/acm/contest/3007/J
现有一个边长为正整数的三角形,问能否以其三个顶点为圆心画三个圆,使三个圆两两外切,三边长均不超过10^8
输入描述:
三个正整数,表示三角形的边长
输出描述:
如果三条边不能构成三角形,输出“wtnl”
如果三条边能构成三角形但不能画出符合要求的圆,输出“No”
否则输出一行“Yes”
然后在第二行输出一组方案,按升序给出三个圆的半径,保留两位小数

不满足三角的定义,输出wtnl,否则二分最小的那个圆的半径,一个半径确定,其他两个圆得半径也就确定了,如果可以放到三角形的三个点上,那就满足条件。

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

int a[3];

int main()
{
    cin>>a[0]>>a[1]>>a[2];
    sort(a,a+3);
    if(a[0] + a[1] <= a[2]|| a[2] - a[1] >= a[0]) {
        cout<<"wtnl"<<endl;
        return 0;
    }
    double x = a[0]*1.0,y = a[1]*1.0,z = a[2]*1.0;
    
    double l = 0, r = x;
    while(r-l>1e-4){
        double mid = (l+r)/2;
        if((x+y-2*mid)>=z) l = mid;
        else r = mid;
    }
    if(x+y-2*l -z>1e-4) cout<<"No"<<endl;
    else {
        double b[3] = {l,x-l,y-l};
        sort(b,b+3);
        cout<<"Yes"<<endl;
        printf("%.2lf %.2lf %.2lf\n",b[0],b[1],b[2]);
    }
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读