PASCAL 数列分段

用PASCAL语言写。顺便说下思路。多谢【问题描述】对于给定的一个长度为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。【输入文件】输入文件divide_b.in的第1行包含两个正整数N,M,第2行包含N个空格隔开的非负整数A[i],含义如题目所述。【输出文件】输出文件divide_b.out仅包含一个正整数,即每段和最大值最小为多少。【样例输入】5 34 2 4 5 1【样例输出】6【数据规模与约定】对于20%的数据,有N≤10;对于40%的数据,有N≤1000;对于100%的数据,有N≤100000,M≤N, A[i]之和不超过109。
2026年09月26日 09:17
有3个网友回答
网友(1):

二分答案,即二分查找每段的最大和
首先设一个值,我这里是S,这个是假设的分段和的最大值,然后依据这个S来进行贪心分组(容易证明贪心的正确性),分组结果和m比较,然后决定增大S还是减少S.

var i,j,k,l,n,m,t1,t2,s,g:longint;
a:array[1..100010]of longint;

function max(a,b:longint):longint;
begin
if(a>b)then exit(a);
exit(b);
end;

function divide:longint;
var i,k,t:longint;
begin
k:=0;
t:=0;
for i:=1 to n do begin
if(t+a[i] > s)then begin
t:=0;
inc(k);
end;
inc(t,a[i]);
end;
inc(k);
exit(k);
end;

begin
readln(n,m);
for i:=1 to n do begin
read(a[i]);
s:=max(s,a[i]);
inc(t2,a[i]);
end;

t1:=s;

s:=s*2;

repeat
k:=divide();
if(k>m)then begin
t1:=s+1;
s:=(t1+t2)div 2;
end
else begin
t2:=s-1;
s:=(t1+t2)div 2;
end;
until t1>=t2;
writeln(t2);
end.

网友(2):

师大附中的题吧 ?
var
a:array[0..100000] of longint;
n,k,min,max,ans:longint;
//=================================
procedure init;
var
i:longint;
begin
readln(n,k);
min:=0;
max:=0;
for i:=1 to n do
begin
read(a[i]);
if min max:=max+a[i];
end;
end;
//=================================
function cut(m:longint):boolean;
var
sum,num,i:longint;
begin
sum:=0;
num:=1;
for i:=1 to n do
if sum+a[i]>m then
begin
inc(num);
sum:=a[i];
end
else
sum:=sum+a[i];
if num>k then exit(false)
else exit(true);
end;
//================================
procedure search;
var
l,r,mid:longint;
begin
l:=min; r:=max;
while l<>r do
begin
mid:=(l+r) shr 1;
if cut(mid) then r:=mid
else l:=mid+1;
end;
ans:=l;
end;
//================================
procedure print;
begin
writeln(ans);
end;
//================================
begin
assign(input,'divide_b.in');
reset(input);
assign(output,'divide_b.out');
rewrite(output);
init;
search;
print;
close(input);
close(output);
end.
思路汤哥的PPT有呀 就是二分

网友(3):

哥,我服了