2016级算法期末模拟练习赛-C.AlvinZH的青春记忆II

Posted AlvinZH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016级算法期末模拟练习赛-C.AlvinZH的青春记忆II相关的知识,希望对你有一定的参考价值。

1084 AlvinZH的青春记忆II

思路

中等题,二分。

简化题意,一列数字,每秒会自动-1,特殊操作可以使一个数在1s内-k,问这些数都减至0需要多久。

答案肯定在[1,xMax]之间,采用二分的方法找到最小时间。

如何判断一个时间值是否符合要求呢?对于≤mid的数,自然消减就好,对于>mid的数,需要特殊操作,设特殊操作次数为s,则有 \(k*s + (mid-s) = Xi\),解得 \(s = (X[i]-mid) / (k-1)\)

分析

注意三个问题,

第一,除0问题,k-1可能为0,需要提前特判,如果k==1,那个和自然递减没有差别,答案直接输出xMax。

第二,式子中有可能会出现小数,如何处理?向上取整!\(s = ceil(1.0*(X[i]-mid) / (k-1))\)

第三,计算过程中s需要多次叠加,有可能会超过int范围,需要使用long long。

参考代码

//
// Created by AlvinZH on 2017/12/9.
// Copyright (c) AlvinZH. All rights reserved.
//

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

int n, k;
int X[100000+10];
int Xmax;

int main ()
{
    while(~scanf("%d %d", &n, &k))
    {
        Xmax = 0;
        for(int i = 0; i < n; i++)
        {
            scanf("%d", &X[i]);
            if(X[i] > Xmax)
                Xmax = X[i];
        }
        if(k == 1)
        {
            printf("%d\n", Xmax);
            continue;
        }

        int ans = 0;
        int l = 1, r = Xmax, mid;
        while (r >= l)
        {
            mid = (l+r)/2;

            long long cnt = 0;
            for (int i = 0; i < n; i++)
            {
                if(X[i] > mid)
                {
                    long long s = ceil(1.0*(X[i]-mid) / (k-1));
                    cnt += s;
                }
            }
            if (cnt > mid)
                l = mid+1;
            else
                r = mid-1, ans = mid;
        }
        printf ("%d\n", ans);
    }
}

以上是关于2016级算法期末模拟练习赛-C.AlvinZH的青春记忆II的主要内容,如果未能解决你的问题,请参考以下文章

2016级算法期末模拟练习赛-B.AlvinZH的青春记忆I

2016级算法期末模拟练习赛-F.AlvinZH的青春记忆IV

2016级算法期末模拟练习赛-E.AlvinZH的青春记忆III

2016级算法期末模拟练习赛-A.wuli51和京导的毕业旅行

A1-2017级算法第一次上机练习赛 C AlvinZH去图书馆

2016级算法第三次上机-C.AlvinZH的奇幻猜想——三次方