绕圈跑*纪中*2390*数学方法/树状数组

题目大意

  Farmer John决定调查开展“奶牛赛跑运动”的可能性。   他将N头奶牛(1 <= N <= 100,000),放在一个长度为C的圆形跑道上。奶牛们沿圆形跑道,跑L圈。   所有奶牛起点都相同,跑步的速度不同。   当最快的奶牛跑完距离L*C的时候,比赛结束。   FJ注意到,有些时候一头奶牛会超过另一个奶牛。   他在思考,整个比赛中,这类“超车事件”会发生多少次。   更具体的说,一个“超车事件”指的是:   一对奶牛(x,y)和一个时间t(小于等于比赛结束时间),在时间t奶牛x超过前面的奶牛y。  请帮FJ计算整个比赛过程中,“超车事件”发生的次数。


分析

  又是他*2——olahiuj

  这道题我实在是不想说些什么了,自行理解。

  或着看——

 Let us define L(i) as the number of laps cow i performs until the race ends. For simplicity, we will think of L(i) as a real number, although in the implementation below we can manage to do all of our math in integers (always a good idea, to avoid round-off issues). If L(i) > L(j), then the number of times cow i crosses cow j is given by the floor of L(i)-L(j). Our goal is therefore to sum up floor(L(i)-L(j)) over all i>j (assuming the cows are ordered in increasing order of L(i)).

 If all we had to do was sum up L(i)-L(j) over all i>j, this would be easy: we would first precompute the prefix sums P(j)=L(1)+...+L(j), and then we can write the sum of L(i)-L(j) over all i>j as the sum of jL(i)-P(i) over all i; this can be therefore computed in linear time. The floor function is really the tricky aspect of this problem. To deal with this properly, we start by setting each L(i) to its floor, and by computing prefix sums as before. We then sum up jL(i)-P(i) over all i, but in increasing order of the fractional part of L(i). As we proceed, we add +1 to each L(i) we encounter (and adjust the prefix sums accordingly, using an appropriate data structure like a binary index tree). Travis' code below shows how to implement this idea.

                                                            -------致看懂的童鞋:请在评论中吱一声,谢谢。

代码
type
  arry=array[0..100010] of longint;
var
  d,num:array[0..100010] of longint;
  b:array[1..200010] of longint;
  i,j,k:longint;
  n,l,c:longint;
  ans:int64;

procedure qsort(var a:arry;l,r:longint);
var
  i,j,k:longint;
  mid:longint;
  temp:longint;
begin
  if (l>=r)
    then exit;
  i:=l; j:=r;
  mid:=a[(l+r) div 2];
  repeat
    while a[i]<mid do i:=i+1;
    while a[j]>mid do j:=j-1;
    if i<=j
      then
        begin
          temp:=a[i]; a[i]:=a[j]; a[j]:=temp;
          i:=i+1; j:=j-1;
        end;
  until i>j;
  qsort(a,l,j);
  qsort(a,i,r);
end;

procedure bian(p,c:longint);
begin
  while p<=d[n]+1 do
    begin
      b[p]:=b[p]+c;
      p:=p+(p and (p xor (p-1)));
    end;
end;

function tong(p:longint):longint;
begin
  tong:=0;
  while p>0 do
    begin
      tong:=tong+b[p];
      p:=p-(p and (p xor (p-1)));
    end;
end;
begin
  readln(n,l,c);
  for i:=1 to n do
    readln(d[i]);
  qsort(d,1,n);
  for i:=1 to n do
    begin
      j:=trunc(d[i]*l/d[n]);
      num[i]:=num[i-1]+j;
      k:=d[i]*l mod d[n];
      bian(k+1,1);
      ans:=ans+j*i-num[i]-i+tong(k+1);
    end;
  writeln(ans);
end.





posted @ 2016-07-10 15:11  一个响亮的蒟蒻  阅读(193)  评论(0编辑  收藏  举报