P2307 [JZOJ/中山市市选] 新年礼物

P2307 [JZOJ/中山市市选] 新年礼物

给你一个序列 \(num\{\}\) 代表不同的颜色的物品的数量,每一次选 \(m\) 种物品 \(-1\),问最多选多少次。

显然最多的物品在前面选,不够的后面补,二分即可。

可以用某段树或某块优化让二分只有 \(O(\log N)\)

一次的时间复杂度 \(O(N \log \frac{\sum num\{\}}{m})\)

Const
	total=5000;

var
	num,sum:array[-1..total] of longint;
	n,m,i,l,r,mid,tot,ans:longint;

procedure Swap(var x,y:longint);var t:longint; begin t:=x; x:=y; y:=t; end;

procedure Sort(l,r:longint);
var i,j,s:longint;
begin
    i:=l; j:=r; s:=num[(l+r) >> 1];
    repeat
        while num[i]>s do inc(i);
        while num[j]<s do dec(j);
        if i<=j then begin Swap(num[i],num[j]); inc(i); dec(j); end;
        until i>=j;
    if i<r then Sort(i,r);
    if j>l then Sort(l,j);
end;

begin
	read(n);
	while n<>0 do
	begin
		fillchar(num,sizeof(num),0);
		fillchar(sum,sizeof(sum),0);
		for i:=1 to n do read(num[i]); Sort(1,n);
		for i:=n downto 1 do sum[i]:=sum[i+1]+num[i];
		read(m); l:=num[n]; r:=sum[1] div m; mid:=(l+r) >> 1;
        if m>n then begin writeln(0); read(n); continue; end;
 		while l<=r do
		begin
			mid:=(l+r) >> 1; tot:=0;
            for i:=1 to m do if num[i]<mid then inc(tot,mid-num[i]);
			if (tot<=sum[m+1]) then begin ans:=mid; l:=mid+1; end else r:=mid-1;
		end;
		writeln(ans); read(n);
	end;
end.
posted @ 2019-04-26 12:52  _ARFA  阅读(125)  评论(0编辑  收藏  举报