序列(二分)

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;
}
复制代码

 

 
posted @   陈瑞淞  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示