53 奶牛赛跑
约翰有 N 头奶牛,他为这些奶牛准备了一个周长为 C 的环形跑牛场。所有奶牛从起点同时起跑,
奶牛在比赛中总是以匀速前进的,第 i 头牛的速度为 Vi。只要有一头奶牛跑完 L 圈之后,比赛就立
即结束了。
有时候,跑得快的奶牛可以比跑得慢的奶牛多绕赛场几圈,从而在一些时刻超过慢的奶牛。这就
是最令观众激动的套圈事件了。请问在整个比赛过程中,套圈事件一共会发生多少次呢?
输入格式
• 第一行:三个整数 N, L 和 C, 1 ≤ N ≤ 105 , 1 ≤ L ≤ 25000 , 1 ≤ C ≤ 25000
• 第二行到第 N + 1 行:第 i + 1 行有一个整数 Vi, 1 ≤ Vi ≤ 106
输出格式
• 单个整数:表示整个比赛过程中,套圈的次数之和
样例输入
4 2 100
20
100
70
1
样例输出
4
解释
两头速度快的奶牛会超过两头速度慢的奶牛
各一次
【分析】
稍微思考一下的题我就不会了么- -
算出每头牛跑的圈数(double),因为都是匀速,要超过完整的一圈必须圈数完整的多1。
但是n^2就会很慢。
可以拆成整数部分和小数部分来做,排个序,整数部分先直接减掉前面的,小数部分求逆序对,然后在ans里面减掉。
要用long long
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
#define Maxn 100010
#define LL long long struct node
{
double a;
LL id;
}t[Maxn]; LL c[Maxn],v[Maxn]; LL mymax(LL x,LL y) {return x>y?x:y;}
bool cmp(node x,node y) {return x.a<y.a;}
bool cmp2(node x,node y) {return x.id<y.id;} LL n; void add(LL x,LL y)
{
for(LL i=x;i<=n;i+=i&(-i))
c[i]+=y;
} LL get_ans(LL x)
{
LL ans=;
for(LL i=x;i>=;i-=i&(-i))
ans+=c[i];
return ans;
} int main()
{
LL l,nc;
scanf("%lld%lld%lld",&n,&l,&nc);
for(LL i=;i<=n;i++) scanf("%d",&v[i]);
sort(v+,v++n);
LL sum=,ans=;
for(LL i=;i<=n;i++)
{
t[i].a=(double)(l*1.0*v[i]/v[n]);
LL x=(LL)(t[i].a);
ans+=(i-)*x-sum;
sum+=x;
t[i].a=t[i].a-x;
t[i].id=i;
}
sort(t+,t++n,cmp);
LL p=;
double now=t[].a;
t[].a=;
for(LL i=;i<=n;i++)
{
if(t[i].a-now>0.000001) p++,now=t[i].a;
t[i].a=p;
}
sort(t+,t++n,cmp2);
memset(c,,sizeof(c));
for(LL i=n;i>=;i--)
{
LL x=(LL)(t[i].a);
ans-=get_ans(x-);
add(x,);
}
printf("%lld\n",ans);
return ;
}
usaco 2012 open
2016-10-28 08:35:28