zoukankan      html  css  js  c++  java
  • P1182 数列分段`Section II`

    题目描述

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

    关于最大值最小:

    例如一数列4 2 4 5 142451要分成33段

    将其如下分段:

    [4 2][4 5][1][42][45][1]

    第一段和为66,第22段和为99,第33段和为11,和最大值为99。

    将其如下分段:

    [4][2 4][5 1][4][24][51]

    第一段和为44,第22段和为66,第33段和为66,和最大值为66。

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

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

    输入输出格式

    输入格式:

    11行包含两个正整数N,M。

    22行包含NN个空格隔开的非负整数A_iAi,含义如题目所述。

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    5 3
    4 2 4 5 1
    输出样例#1: 复制
    6

    说明

    对于20\%20%的数据,有N≤10N10;

    对于40\%40%的数据,有N≤1000N1000;

    对于100\%100%的数据,有N≤100000,M≤N, A_iN100000,MN,Ai之和不超过10^9109。

    思路: 二分+贪心

    最后判断的时候注意:

     在同样满足条件的情况下(即等于题目要求的分组数时), 看看有没有更小的

    最终输出最后一组left(left>right时自动跳出循环)

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int MAX = 100010;
    
    int n, m, a[MAX];
    
    bool judge(int mid)
    {
    	int sum = 0, count = 1;
    	for(int i = 1; i <= n; ++i)
    	{
    		if(sum + a[i] > mid)
    		{
    			sum = a[i];
    			count++;
    		}
    		else
    		{
    			sum = sum + a[i];
    		}
    	}
    	if(count > m)
    		return true;
    	else
    		return false;
    }
    
    int main()
    {
    	int left = 0, right = 0;
    	int i, mid, ans;
    	cin >> n >> m;
    	for(i = 1; i <= n; ++i)
    	{
    		cin >> a[i];
    		left = max(left, a[i]);
    		right = right + a[i];
    	}
    	while(left <= right)
    	{
    		mid = left + (right - left)/2;
    		if(judge(mid))
    		{
    			left = mid + 1;
    		}
    		else
    		{
    			right = mid - 1;
    			ans = mid;
    		}
    	}
    	cout << ans << endl;
    	return 0;
    }
    

      

    #include<stdio.h>
    #define MAX 100010
    
    int n, m, left, right, mid, ans, a[MAX];
    int max1, sum, count;
    
    int max(int a, int b)
    {
        return (a > b ? a : b);
    }
    
    int main()
    {
        int i;
        scanf("%d %d", &n, &m);
        for(i = 0; i < n; ++i)
        {
            scanf("%d", &a[i]);
            max1 = max(max1, a[i]);
            sum = sum + a[i];
        }
        left = max1, right = sum;
        while(left <= right)
        {
            count = 1;
            sum = 0;
            mid = left + (right - left) / 2;
            for(i = 0; i < n; ++i)
            {
                if(sum + a[i] <= mid)
                {
                    sum = sum + a[i];
                }
                else
                {
                    sum = a[i];
                    count++;
                }
            }
            if(count > m)
            {
                left = mid + 1;
            }
            else
            {
                right = mid - 1;
            }
        }
    
        printf("%d
    ", left);
        return 0;
    }

      

  • 相关阅读:
    ThinkPHP3.1快速入门(12)自动验证
    ThinkPHP CURD方法盘点:page方法
    ThinkPHP CURD方法盘点:table方法
    ThinkPHP CURD方法盘点:order方法
    ThinkPHP CURD方法盘点:data方法
    openssl安装问题导致nginx添加ssl模块失败
    rsync介绍
    基于CRF序列标注的中文依存句法分析器的Java实现
    千万级巨型汉语词库分享
    几个开源分词系统所使用标注集的来源
  • 原文地址:https://www.cnblogs.com/mjn1/p/10271132.html
Copyright © 2011-2022 走看看