机密文件
题目描述:OI总部最近得到可靠消息,近日来怪盗基德会再次来OI总部盗窃机密文件(因为是机密,所以不能透露),所以OIER得在怪盗基德来临之前就把文件备份。不过,正好今天OI总部停电了,所以就得人工抄写了。现在,OI总部内一共有M份资料和K个OIER(S),需要将每一份资料都备份一份,M份资料的页数不一定相同(有不同的,也有相同的)。现在,你作为其中的一名OIER,把资料分配给OIER备份,由于人太多了,所以每一名OIER所分配到的资料都必须是连续顺序的,并且每一名OIER的备份速度是相同的。你的任务就是让备份的时间最短,列出最短的方案。数据可能存在多个解,所以,当存在多个解时,让前面的人少备份。
输入:输入文件中的第一行为两个整数M,K,分别表示书本的数目和OIER的人数。
第二行中为由M个分隔的整数构成,分别表示M本书的页数。其中:第i份资料的编号为i。
输出:输出文件中共有K行,每行有两个整数。其中:第i行中表示第i个OIER备份的资料编号的起止。
样例输入:
8 3
1 2 3 4 5 6 7 8
这道题其实就是二分答案,从后往前判断(注意:每个人手里都要有抄写任务,所以要加一个特判:如果剩余人数=剩余书本数,就强制一人一本)。
代码:
var
n,m,i,j,k,x,y,z,s,ls,l,r,mid:longint;
a:array[0..1001]of longint;
f:array[0..1001,1..2]of longint;
function pd(k:longint):boolean;
var
i,j,x,y,z,s,ls:longint;
o:array[0..1001,1..2]of longint;
begin
fillchar(o,sizeof(o),0);
ls:=0;
for i:=n downto 1 do
begin
if i=n then
begin
inc(o[0,1]);
o[o[0,1],1]:=i;
inc(ls,a[n]);
end
else
begin
if i=m-o[0,1] then
begin
o[o[0,1],2]:=i+1;
inc(o[0,1]);
o[o[0,1],1]:=i;
o[o[0,1],2]:=i;
end
else
begin
if ls+a[i]>k then
begin
o[o[0,1],2]:=i+1;
inc(o[0,1]);
if o[0,1]>m then exit(false);
o[o[0,1],1]:=i;
ls:=a[i];
end
else inc(ls,a[i]);
end;
end;
end;
o[o[0,1],2]:=1;
f:=o;
exit(true);
end;
begin
assign(input,'secret.in');
reset(input);
assign(output,'secret.out');
rewrite(output);
readln(n,m);
l:=-maxlongint;
for i:=1 to n do
begin
read(a[i]);
inc(r,a[i]);
if a[i]>l then l:=a[i];
end;
while l<=r do
begin
mid:=(l+r) p 2;
if pd(mid) then r:=mid-1
else l:=mid+1;
end;
for i:=m downto 1 do
writeln(f[i,2],' ',f[i,1]);
end.