Description
Farmer John决定调查开展“奶牛赛跑运动”的可能性。
他将N头奶牛(1 <= N <= 100,000),放在一个长度为C的圆形跑道上。奶牛们沿圆形跑道,跑L圈。
所有奶牛起点都相同,跑步的速度不同。
当最快的奶牛跑完距离L*C的时候,比赛结束。
FJ注意到,有些时候一头奶牛会超过另一个奶牛。
他在思考,整个比赛中,这类“超车事件”会发生多少次。
更具体的说,一个“超车事件”指的是:
一对奶牛(x,y)和一个时间t(小于等于比赛结束时间),在时间t奶牛x超过前面的奶牛y。
请帮FJ计算整个比赛过程中,“超车事件”发生的次数。
Input
第1行:三个空格隔开的整数:N,L和C。(1 <= L,C <= 25,000)。
第2..N+1行:第i+1行包含奶牛i的速度,一个整数,范围1..1,000,000。
Output
第1行:整个比赛过程中,“超车事件”发生的总次数。
Sample Input
4 2 100
20
100
70
1
Sample Output
4
Hint
[样例解释]
有4头奶牛,跑2圈,圆形跑道的长度为100。
奶牛们的速度分别是:20,100,70和1。
比赛持续2单位时间,奶牛2花费此时间完成比赛。
在这段时间里,发生了4次“超车事件”:奶牛2超过奶牛1和4,奶牛3超过奶牛1和4。
[数据范围]
有60%的数据满足N<=5000
分析:
对于给定的速度从小到大排序,设L为圈数,C为总距离,S[i]为第i只奶牛的速度
L∗Cmax(S)就是比赛的总时间
对于第i只奶牛能跑S[i]∗C∗Lmax(S)C
约分得:⌊S[i]∗Lmax(S)⌋,记为q[i],余数记为t[i]
对于每一只奶牛,只要查找在她之前的奶牛个数
于是我们就会发现神奇的情况
若有⌊a−b⌋,a、b分别表示圈数,则分情况讨论
a的小数部分<b的小数部分,则⌊a−b⌋=⌊a⌋−⌊b⌋,反之为⌊a⌋−⌊b⌋−1
于是我们的任务又变成了求多加了多少1,维护一个树状数组累加余数t,统计余数小于当前奶牛的圈数的余数的个数就行了
代码实现/pas
var
n,l,c:Longint;
a,q,t:array[0..100000]of longint;
f:array[1..1000000]of longint;
procedure add(x:longint);
begin
inc(x);
while x<=a[n] do
begin
inc(f[x]);
x:=x+(x and(-x));
end;
end;
function get(x:longint):longint;
begin
inc(x);
get:=0;
while x>0 do
begin
get:=get+f[x];
x:=x-(x and(-x));
end;
end;
procedure qsort(l,r:longint);
var
x,y,key,tmp:longint;
begin
if l>=r then exit;
x:=l;
y:=r;
key:=a[l+random(r-l+1)];
repeat
while (a[x]<key) do inc(x);
while (a[y]>key) do dec(y);
if x<=y then
begin
tmp:=a[x];
a[x]:=a[y];
a[y]:=tmp;
inc(x);
dec(y);
end;
until x>y;
qsort(l,y);
qsort(x,r);
end;
procedure main;
var
i,sum,t,v:longint;
ans:int64;
begin
sum:=0;
ans:=0;
for i:=1 to n do
begin
t:=a[i]*l mod a[n];
add(t);
q[i]:=a[i]*l div a[n];
inc(sum,q[i]);
v:=q[i]*i-sum;
dec(v,i-get(t));
ans:=ans+v;
end;
writeln(ans);
end;
procedure init;
var
i:longint;
begin
readln(n,l,c);
for i:=1 to n do
read(a[i]);
qsort(1,n);
end;
begin
randomize;
init;
main;
end.