T^T online judge 3689
毒瘤题2
TimeLimit:1000MS MemoryLimit:128MB
64-bit integer IO format:%lld
已解决 | 点击收藏
Problem Description
cantaloup最近在准备春招,所以向cwl要了很多有关面试的书籍,这些书籍加起来一共有m页,这对于cantaloupe来说实在是太多了。所以他买了n瓶不同大小的FeiZhaiKuaiLeShui,每一瓶都可以增加cantaloupe想看书的心情值,增加的心情值取决于瓶子容量,但是如果在同一天喝了不止一瓶的就会降低功效。同一天,假设喝的第二瓶的容量为10,那么增加的心情值就会是9(即10-1),喝的第三瓶的容量为10,那么增加的心情值就会是8(即10-2)......cantaloupe想知道以目前买的FeiZhaiKuaiLeShui可不可以支撑他看完那些书,最快能在几天内看完?(1点心情看一页,可乐不一定要喝完,加成为负时可以选择不喝)
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; }