[二分答案] Copying Books
上次做到那个收入计划的时候就提到了这道题目,在POJ上是让输出方案,并且保证前面的人赋值的书稿尽量多。所以不需要SJ。
具体实现就是先二分出正确的答案,然后根据答案从后往前进行贪心划分。
[pascal 代码]
VAR A,WAY:ARRAY[0..100000]OF LONGINT; N,M,L,R,MID,I,J,TOT,T,IT:LONGINT; FUNCTION CHECK(P:LONGINT):BOOLEAN; VAR PRE,I:LONGINT; BEGIN TOT:=M; PRE:=0; I:=1; WHILE I<=N DO BEGIN IF PRE+A[I]<=P THEN BEGIN PRE:=PRE+A[I]; INC(I); END ELSE BEGIN PRE:=0; DEC(TOT); IF TOT=0 THEN EXIT(FALSE); END; END; EXIT(TRUE); END; PROCEDURE GETWAYS(P:LONGINT); VAR PRE,I,TOT:LONGINT; BEGIN TOT:=0; PRE:=0; I:=N; WHILE I>=1 DO BEGIN IF (PRE+A[I]<=P)AND(M-TOT<=I) THEN BEGIN PRE:=PRE+A[I]; DEC(I); END ELSE BEGIN PRE:=0; INC(TOT); WAY[TOT]:=I; IF TOT=0 THEN EXIT; END; END; END; BEGIN READLN(T); FOR IT:=1 TO T DO BEGIN READLN(N,M); R:=0;L:=0; FOR I:=1 TO N DO BEGIN READ(A[I]); R:=R+A[I]; END; WHILE L<R DO BEGIN MID:=(L+R)>>1; IF CHECK(MID) THEN R:=MID ELSE L:=MID+1; END; //WRITELN(L); GETWAYS(L); L:=1; FOR I:=M-1 DOWNTO 1 DO BEGIN R:=WAY[I]; FOR J:=L TO R DO WRITE(A[J],' ');WRITE('/ '); L:=R+1; END; FOR I:=L TO N DO WRITE(A[I],' ');WRITELN; END; END.