• 数列分段II(信息学奥赛一本通 1436)(洛谷 1182)


    【题目描述】

    对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小。

    关于最大值最小:

    例如一数列4 2 4 5 1要分成3段

    将其如下分段:

    [4 2][4 5][1]

    第一段和为6,第2段和为9,第3段和为1,和最大值为9。

    将其如下分段:

    [4][2 4][5 1]

    第一段和为4,第2段和为6,第3段和为6,和最大值为6。

    并且无论如何分段,最大值不会小于6。

    所以可以得到要将数列4 2 4 5 1要分成3段,每段和的最大值最小为6。

    【输入】

    第1行包含两个正整数N,M,第2行包含N个空格隔开的非负整数A[i],含义如题目所述。

    【输出】

    仅包含一个正整数,即每段和最大值最小为多少。

    【输入样例】

    5 3
    4 2 4 5 1

    【输出样例】

    6

    最小值最大(或是最大值最小)问题,这类双最值问题常常选用二分法求解。本题就是一道典型的“二分答案”模型。
    因为每段和最大值的取值区间是[ max(a[1],a[2],a[3]……a[n]) , sum(a[1],a[2],a[3]……a[n]) ],所以就二分l和r,令mid=l+r>>1,每次进行check,计算当mid为最大值的情况下可以分成的段数cnt,

    • 若cnt>m,说明这个mid小了,则令l=mid+1;

    • 若cnt<=m,说明这个mid大了,则令r=mid-1,由于此时cnt可能等于m,所以用ans记录下来;

    详见代码——

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=1e6+5;
     4 int a[N];
     5 int n;
     6 int m,q,w,ans,p,tot;
     7 int read()
     8 {
     9     int f=1;char ch;
    10     while((ch=getchar())<'0'||ch>'9')
    11         if(ch=='-')f=-1;
    12     int res=ch-'0';
    13     while((ch=getchar())>='0'&&ch<='9')
    14         res=res*10+ch-'0';
    15     return res*f;
    16 }
    17 void write(int x)
    18 {
    19     if(x<0)
    20     {
    21         putchar('-');
    22         x=-x;
    23     }
    24     if(x>9)write(x/10);
    25     putchar(x%10+'0');
    26 }
    27 bool check(int s)
    28 {
    29     int cnt=1,now=0;
    30     for(int i=1;i<=n;i++)
    31     {
    32         if(a[i]+now<=s)now+=a[i];
    33         else
    34         {
    35             cnt++;
    36             now=a[i];
    37         }
    38     }
    39     return cnt<=m;
    40 }
    41 int main()
    42 {
    43     n=read();m=read();int ma=-1,sum=0;
    44     for(int i=1;i<=n;i++)
    45     {
    46         a[i]=read();
    47         ma=max(ma,a[i]);
    48         sum+=a[i];
    49     }
    50     int l=ma,r=sum;
    51     while(l<=r)
    52     {
    53         int mid=l+r>>1;
    54         if(check(mid))
    55         {
    56             ans=mid;r=mid-1;
    57         }
    58         else l=mid+1;
    59     }
    60     write(ans);
    61     return 0;
    62 }
  • 相关阅读:
    图片处理帮助类
    网站前端的优化
    状态码大全
    服务端性能监控工具Nmon使用方法
    jmeter测试报告解析
    jmeter聚合报告
    jmeter跨线程组调用参数
    jmeter生成测试报告
    Jmeter获取cookie
    monkey的使用方法和常见命令
  • 原文地址:https://www.cnblogs.com/ljy-endl/p/11388118.html
Copyright © 2020-2023  润新知