T^T online judge 3689

毒瘤题2

TimeLimit:1000MS  MemoryLimit:128MB
64-bit integer IO format:%lld
Special Judge
已解决 | 点击收藏
Problem Description

cantaloup最近在准备春招,所以向cwl要了很多有关面试的书籍,这些书籍加起来一共有m页,这对于cantaloupe来说实在是太多了。所以他买了n瓶不同大小的FeiZhaiKuaiLeShui,每一瓶都可以增加cantaloupe想看书的心情值,增加的心情值取决于瓶子容量,但是如果在同一天喝了不止一瓶的就会降低功效。同一天,假设喝的第二瓶的容量为10,那么增加的心情值就会是9(即10-1),喝的第三瓶的容量为10,那么增加的心情值就会是8(即10-2)......cantaloupe想知道以目前买的FeiZhaiKuaiLeShui可不可以支撑他看完那些书,最快能在几天内看完?(1点心情看一页,可乐不一定要喝完,加成为负时可以选择不喝)

可乐.jpg

Input

单组数据

第一行输入n(n<=200000),m(m<=1000000000)

第二行输入n个数字ai代表第i瓶的容量

0<ai<=1e9

 

Output

输出一个整数,代表最快能在几天内看完,看不完输出-1

SampleInput
 
SampleOutput
 
 
【思路】:比赛的时候有点自闭了,没💡,比赛后tm一眼正解。。。。
    简直了,这个题目就是一个二分,枚举天数,枚举1 ~n天
    我们要怎么创造出n天的最大价值呢?
    其实很简单,把数据sort一下,从大到小,然后平分到n堆里面。
    这样肯定是最优秀的。(有个坑点:如果为0 或小于0就不能分到对应的堆里面)
    💭💡🎈
那么附上代码:
    
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
/**
 我觉得这个题目还可以考虑一下倍增
 **/
typedef long long ll;
const int MAXN = 200000 + 5;
bool cmp(const ll &a, const ll &b)
{
    return a > b;
}
ll arr[MAXN];
ll n, m;
bool judge(int x)///代表分成x个堆
{
    ll sum = 0;
    for(int i = 0; i < n; i ++)
    {
        if((arr[i] - i / x) > 0)
            sum += (arr[i] - i / x);
        else
            break;
    }
    if(sum >= m)
        return true;
    else
        return false;
}
int acfinds()
{
    int l = -1, r = n;
    while(l + 1 < r)
    {
        int mid = (l + r) / 2;
        if(mid && judge(mid))
        {
            r = mid;
        }
        else
        {
            l = mid;
        }
    }
    return r;
}
int main()
{
    while(~scanf("%lld%lld", &n, &m))
    {
        ll sum = 0;
        for(int i = 0; i < n; i ++)
        {
            scanf("%lld", &arr[i]);
            sum += arr[i];
        }
        sort(arr, arr + n, cmp);
        if(sum < m)
        {
            printf("-1\n");
        }
        else
        {
            int ans = acfinds();
            printf("%d\n", ans);
        }
    }
    return 0;
}

 

  
 附上倍增写法,比二分快100ms
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
/**
 我觉得这个题目还可以考虑一下倍增
 **/
typedef long long ll;
const int MAXN = 200000 + 5;
bool cmp(const ll &a, const ll &b)
{
    return a > b;
}
ll arr[MAXN];
ll n, m;
bool judge(int x)///代表分成x个堆
{
    ll sum = 0;
    for(int i = 0; i < n; i ++)
    {
        if((arr[i] - i / x) > 0)
            sum += (arr[i] - i / x);
        else
            break;
    }
    if(sum >= m)
        return true;
    else
        return false;
}
int acfinds()
{
    /**
     考虑一下倍增的写法
     **/
    int l = 0;
    int p = 1;
    while(1)
    {
        if(l + p <= n && judge(l + p) == false)
        {
            l = l + p;
            p = p * 2;
        }
        else
        {
            p /= 2;
            if(p == 0)
            {
                return l + 1;
            }
        }
    }
}
int main()
{
    while(~scanf("%lld%lld", &n, &m))
    {
        ll sum = 0;
        for(int i = 0; i < n; i ++)
        {
            scanf("%lld", &arr[i]);
            sum += arr[i];
        }
        sort(arr, arr + n, cmp);
        if(sum < m)
        {
            printf("-1\n");
        }
        else
        {
            int ans = acfinds();
            printf("%d\n", ans);
        }
    }
    return 0;
}

 

posted @ 2019-03-27 22:38  moxin0509  阅读(273)  评论(0编辑  收藏  举报