题目大意:
你和你的K-1个好友的周围满是礼物,你发扬你帅气的风格,让你的好友先拿,你最后拿,每个人只能拿当前离自己最近的礼物(有多个距离相等的礼物可以全部拿走)(距离精确到小数后四位,所有运算均为去尾)。
大家都处于原点(0,0),给出每个礼物的坐标(x,y)以及是谁送的。要你找出你的礼物离你的距离D,你能拿到的礼物数量U,一次U个礼物分别是谁送的,按输入顺序输出。若拿不到礼物,则输出“555”。
对于30%的数据 K≤N≤1000
对于所有的数据 K≤N≤100000
所有的坐标绝对值小于10^6
题解:
排序+枚举:
因为题目中出现的距离要精确到小数点后4位,所以我们可以先将我们处理出来的距离a[i]*10000,注意处理过程要开int64,C++则开long long。
然后我们将a[i]排序,记得排序的时候相等时按输入顺序跟着排,然后处理K-1个人拿到的礼物,设前i-1个礼物是K-1个人的,则a[i]是给K的(a已排序),然后将连续的一段[i,j]输出对应的名字。
其中[i,j]这一段内所有的a[]都相等。
时间复杂度:O(NT)
T介于1~名字的最长长度之间
var
a:array [0..100001] of int64;
ans,b:array [0..100001] of longint;
c:array [0..100001] of ansistring;
i,j,n,m:longint;
p,q,s:ansistring;
x,y:int64;
procedure qsort(l,r:longint);
var
i,j,kp:longint;
mid:int64;
begin
if l>=r then exit;
i:=l; j:=r;
mid:=a[(l+r) div 2];
kp:=b[(l+r) div 2];
repeat
while (a[i]<mid) or ((a[i]=mid) and (b[i]<kp)) do inc(i);
while (a[j]>mid) or ((a[j]=mid) and (b[j]>kp)) do dec(j);
if i<=j then
begin
a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
inc(i); dec(j);
end;
until i>j;
qsort(i,r);
qsort(l,j);
end;
begin
readln(n,m);
for i:=1 to n do
begin
readln(s);
j:=pos(' ',s); c[i]:=copy(s,1,j-1);
delete(s,1,j); j:=pos(' ',s);
p:=copy(s,1,j-1); val(p,x);
q:=copy(s,j+1,length(s)-j); val(q,y);
a[i]:=trunc(sqrt(sqr(x)+sqr(y))*10000);
b[i]:=i;
end;
qsort(1,n);
i:=1; j:=0;
while i<=n do
begin
inc(j);
if j=m then
begin
ans[0]:=1;
ans[1]:=b[i];
while a[i]=a[i+1] do
begin
inc(i);
inc(ans[0]);
ans[ans[0]]:=b[i];
end;
writeln(a[i] div 10000,' ',ans[0]);
for j:=1 to ans[0] do writeln(c[ans[j]]);
halt;
end
else while a[i]=a[i+1] do inc(i);
inc(i);
end;
writeln('555');
end.