P1182 Sequence segment `Section II` (the most pitted two divisions I have done so far)

Topic description

For a given positive integer sequence Ai of length N, it is now divided into M (M≤N) segments, and each segment is required to be continuous, and the maximum value of the sum of each segment is the smallest.

About max min:

For example, a sequence 4 2 4 5 1 should be divided into 3 segments

Break it down as follows:

[4 2][4 5][1]

The sum of the first segment is 6, the sum of the second segment is 9, the sum of the third segment is 1, and the maximum value is 9.

Break it down as follows:

[4][2 4][5 1]

The sum of the first segment is 4, the sum of the second segment is 6, the sum of the third segment is 6, and the maximum value is 6.

And no matter how segmented, the maximum value will never be less than 6.

Therefore, it can be obtained that the sequence 4 2 4 5 1 needs to be divided into 3 segments, and the maximum value of the sum of each segment is at least 6.

Input and output format

Input format:

 

Line 1 contains two positive integers N,M.

Line 2 contains N space-separated non-negative integers Ai​, the meaning is as described in the title.

 

Output format:

 

A positive integer, that is, the minimum value of each segment and the maximum value.

 

Input and output example

Input Example #1:  Copy

5 3
4 2 4 5 1

Output Sample #1:  Copy

6

illustrate

For 20% of the data, there are N≤10;

For 40% of the data, there are N≤1000;

For 1100% data, there are N≤100000, M≤N, and the sum of Ai​ does not exceed 10^9.

 


Ideas:

To be honest, if you see the minimum and maximum values ​​in the question, you will know that it is a two-point answer. You can directly put this question on the board and you will cry. You can't even pass the sample.

The check function of this question is a bit difficult to write, and the dichotomy range is also difficult to determine . I used it at first.    

    min_a=min(min_a,a[i]);//找最小值 
    l=min_a,r=s;

In this range, the fourth point will be WA, which can only get 80 points

The dalao to see the solution is used

    max_a=max(max_a,a[i]);
    l=max_a,r=s; 

The range from the largest of all array elements to the sum of the array elements

There is also:

Two-point answer----can't use mid...do you have to use l? ? ? ? ? ? ? ? ? ?


Code:

//最大值最小  那就用二分答案 
#include<iostream>
#include<algorithm>
#include<cstdio>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn= 1e6 + 5 ;
ll a[maxn];
ll n,m;
ll s,max_a=-inf; 

inline bool check(ll mid) //用mid作为最小的最大值 
{
	ll num=1;
	ll sum=0;
	for(int i=1;i<=n;i++)
	{
		if(sum+a[i]<=mid) //满足小于等于 
			sum+=a[i];
		else//不满足则重置sum,分段数加一 
		{
			sum=a[i];
			num++;		
		}
	}
	if(num>m)	return true;//分段数大于m则真 
	else		return false;
}

int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		max_a=max(max_a,a[i]);
		s+=a[i]; //记录总和 
	}
//	ll l=min_a,r=s;  //只有80分
	ll l=max_a,r=s; 
	while(l<=r)
	{
		ll mid=(l+r)>>1;
		if(check(mid)) //看见没,没有ans 
			l=mid+1;	
		else
			r=mid-1;	
	}	
	cout<<l<<endl;  //输出l 
	return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326390233&siteId=291194637