序列(二分)
1769: 序列
题目描述
给定一个长度为n的序列,要求将其分成m段序列,每一段连续,并使得每一段和的最大值尽可能小。
输入
第一行两个整数n,m。
第二行n个整数,代表序列。
输出
一行一个整数,代表每一段和的最大值的最小值。
样例输入
5 3
4 2 4 5 1
样例输出
6
分析:
我们首先要二分出最大值的最小值
没啥好说的:
scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&a[i]); int r=2e9,l=0; while(l+1!=r) { int mid=(l+r)/2; if(check(mid)/*如果符合*/==1) { r=mid; } else { l=mid; } }
如何判断最小呢?
先看样例
假设最小值是6
我们先让4当一段的开始
再看2,4+2<=6,所以让4 2形成一段
由于4+6>6
那么后面的4就又是一段的开始,以此类推
所以函数check这样写:
int check(int k) { int ans=0,num=0; for(int i=1; i<=n; i++) { if(a[i]>k) { return 0; } if(a[i]+num<=k) { num+=a[i]; } else { num=a[i]; ans++; } } ans++; if(ans<=m) { return 1; } else { return 0; } }
ok
全代码:
#include<bits/stdc++.h> using namespace std; int n,m,a[1e6+10]= {0}; int check(int k) { int ans=0,num=0; for(int i=1; i<=n; i++) { if(a[i]>k) { return 0; } if(a[i]+num<=k) { num+=a[i]; } else { num=a[i]; ans++; } } ans++; if(ans<=m) { return 1; } else { return 0; } } int main() { scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); } int r=2e9,l=0; while(l+1!=r) { int mid=(l+r)/2; if(check(mid)==1) { r=mid; } else { l=mid; } } printf("%d",r); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现