#P2999. USACO(53)树状数组2:奶牛赛跑P3054 [USACO12OPEN] Running Laps S

USACO(53)树状数组2:奶牛赛跑P3054 [USACO12OPEN] Running Laps S

Description

【题意】
约翰有 $N$ 头奶牛,他为这些奶牛准备了一个周长为 $C$ 的环形跑牛场。
所有奶牛从起点同时起跑,奶牛在比赛中总是以匀速前进的,第 $i$ 头牛的速度为 $V_i$。
只要有一头奶牛跑完 $L$ 圈之后,比赛就立即结束了。
有时候,跑得快的奶牛可以比跑得慢的奶牛多绕赛场几圈,从而在一些时刻超过慢的奶牛。
这就是最令观众激动的套圈事件了。
请问在整个比赛过程中,套圈事件一共会发生多少次呢?

【输入格式】
第一行:三个整数 $N$,$L$和$C$,$1 ≤ N ≤ 10^5 , 1 ≤ L ≤ 25000 , 1 ≤ C ≤ 25000$
第二行到第 $N+1$ 行:第 $i+1$ 行有一个整数 $V_i$,$ 1 ≤ V_i ≤ 10^6$

【输出格式】
单个整数:表示整个比赛过程中,套圈的次数之和

【样例输入】

4 2 100

20

100
70
1

【样例输出】
4

【解释】

有 4 头奶牛在长度为 100 的圆形轨道上跑 2 圈。奶牛的速度为 20、100、70 和 1。

比赛持续 2 个单位的时间,因为这是最快的奶牛(奶牛 2)完成所需的时间。在这段时间内,有 4 次套圈事件:奶牛 2 超过了奶牛 1 和 4,奶牛 3 超过了奶牛 1 和 4。


Hint

by hansang:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10, M=1e6+10;
LL a[N], c[M]; int n, l, C; 
struct node{LL x, d;} b[N];
void add(LL x, LL w){
    if(x==0) return ;
    for(LL i=x; i>=1; i-=i&-i) c[i]+=w;
}
LL query(LL x){
    LL res=0;
    for(LL i=x; i<=a[n]; i+=i&-i) res+=c[i];
    return res;
}
int main(){
    scanf("%d%d%d", &n, &l, &C);
    for(int i=1; i<=n; i++) scanf("%lld", &a[i]); 
    sort(a+1, a+n+1); LL ans=0;
    for(int i=1; i<=n; i++){
        b[i].x=l*a[i]/a[n];
        b[i].d=l*a[i]%a[n]+1;
        ans+=(i-(n-i+1))*b[i].x;
    }
    memset(c, 0, sizeof(c));
    for(int i=1; i<=n; i++){
        ans-=query(b[i].d+1);
        add(b[i].d, 1);
    }
    printf("%lld\n", ans);
    return 0;
}