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.
完结撒花!✿✿ヽ(゚▽゚)ノ✿