Description
Solution
一道很经典的题目(做过还推了好久没有推出来,惭愧),找出两个平均数的大小关系式子 Sr−Slr−l≥Sr′−Sl′r′−l′ ( Si 表示 ∑ai )。第K大,可以通过二分答案判断得解。设二分出的答案是 mid ,转化形式变成 Si−mid∗i≥Si′−mid∗i′ ,设 Ti=Si−mid∗i ,就能变成求顺序对的个数。用总对数减去逆序对个数就能得出满足的个数,再与K进行大小判断。逆序对可以用归并排序或树状数组来求。
Code
var
l,r,mid:extended;
a:array[0..100000] of longint;
s,t:array[0..100000] of extended;
n,i:longint;
k,sum:int64;
ans:extended;
procedure sort(l,r:longint);
var i,j,k,mid:longint;
begin
if l=r then exit;
mid:=(l+r)div 2;
sort(l,mid);
sort(mid+1,r);
i:=l;j:=mid+1;k:=l;
while (i<=mid)and(j<=r) do
if s[i]<=s[j] then
begin
t[k]:=s[i];
inc(i);inc(k);
end
else
begin
t[k]:=s[j];
inc(j);inc(k);
sum:=sum+mid-i+1;
end;
while i<=mid do
begin
t[k]:=s[i];
inc(i);inc(k);
end;
while j<=r do
begin
t[k]:=s[j];
inc(j);inc(k);
sum:=sum+mid-i+1;
end;
for i:=l to r do s[i]:=t[i];
end;
function pd(x:extended):boolean;
begin
s[0]:=0;
for i:=1 to n do s[i]:=s[i-1]+a[i]-x;
sum:=0;
sort(0,n);
sum:=n*(n+1) div 2-sum;
if sum>=k then exit(true);exit(false);
end;
begin
readln(n,k);
for i:=1 to n do
begin
read(a[i]);
if r<a[i] then r:=a[i];
end;
while l<r-0.00001 do
begin
mid:=(l+r)/2;
if pd(mid) then l:=mid else r:=mid;
end;
writeln(l:0:4);
end.