绕圈跑 (Standard IO)

题意/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行:整个比赛过程中,“超车事件”发生的总次数。

 

题解/solution

       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.

(爱看不看)

 

代码/Code

#include <stdio.h>  
#include <iostream>  
#include <algorithm>  
#include <sstream>  
#include <stdlib.h>  
#include <string.h>  
#include <limits.h>  
#include <string>  
#include <time.h>  
#include <math.h>  
#include <queue>  
#include <stack>  
#include <map>  
using namespace std; 
long long maxx;
long long a[100000],f[100000]; 
long long b[1000000];
int lowbit(int x)
{
	return (x)&(-x);
}

bool cmp(long long a,long long b)
{
	return a<b;
}

int update(int x)
{
	int i=x+1;
	while (i<=maxx)
	{
		b[i]+=1;
		i+=lowbit(i);
	}
}

int getsum(int x)
{
	int sum=0,i=x+1;
	while (i>0)
	{
		sum+=b[i];
		i-=lowbit(i);
	}
	return sum;
}

int main()
{
	int n,l,c;
	cin>>n>>l>>c;
	for (int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	sort(a+1,a+1+n,cmp);
	maxx=a[n];
	for (int i=1;i<=n;i++)
	{
		f[i]=(a[i]*l)/maxx;
	}
	update((a[1]*l)%maxx);
	long long t=f[1],ans=0;
	for (int i=2;i<=n;i++)
	{
		t+=f[i];
		update((a[i]*l)%maxx);
		ans=ans+f[i]*i-t-i;
		ans+=getsum((a[i]*l)%maxx);
	}
	cout<<ans<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/zyx-crying/p/9319660.html