P8198 背单词的小智
题面
小智在刚刚结束的 CET-4 考试中顺利通过了!现在,他要开始备战 CET-6 了。
可是,他的单词功底太差了,于是他准备开始摆烂背单词。
可是,人脑的能力是有限的,小智的大脑每一天都会有一个记忆的上限,如果超过这个上限,再多的单词也记不下了。
有一天,小智在背单词的时候想到了一个问题,你能帮帮他吗?
小智一共有 个单词需要背,第 个单词所拥有的「精神值」为 。
小智每天的记忆力都是有上限 的。如果小智在第 天内背完了 内的单词,那么这些单词将会占用小智 的记忆力。
小智需要在最多 天里把这些单词全部背完,他希望你在把这些单词背完的同时,让他每天需要的记忆力的最大值尽可能小。
也就是说,你需要将一个序列最多分为 段,请你找到一个最小的 ,使得 ,,其中 , 为各段的左、右端点。
数据规模与约定
对于所有测试点,保证 ,,。
思路
思路
这道题明显可以二分答案。
好的,接下来如何写check
函数呢?可以贪心,对于每一个数据,能加上就加上,不能加就重新开一个段。
然后就可以在check
函数中遍历数组,进行累加。如果累加中有一个地方大于了 ,那么计数器++,并把累加器赋值为当前 的值。最后特判计数器 .
代码
记得开long long
!
#include <algorithm>
#include <iostream>
#define int long long
#define SIZE (int)(1e5+5)
using namespace std;
int n,m,lft=0,rgt=0;
int arr[SIZE];
bool check(int x) {
int total=0,number=0;
for(int i=1; i<=n; i++) {
if(total+arr[i]<=x) {
total+=arr[i];
} else {
total=arr[i];
number++;
}
}
if(number>=m) {
return true;
} else {
return false;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1; i<=n; i++) {
cin>>arr[i];
arr[i]=arr[i]*arr[i];
lft = max(lft,arr[i]);
rgt += arr[i];
}
while(lft<=rgt) {
int mid = (lft+rgt)>>1;
if(check(mid)) {
lft=mid+1;
} else {
rgt = mid-1;
}
}
cout<<lft;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现