欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

逆序对——P3054 [USACO12OPEN]跑圈Running Laps

程序员文章站 2022-03-03 20:13:01
...

题目描述

农夫约翰让他的 n (1 <= n <= 100,000) 头牛在长度为 c 的跑道上进行跑 l 圈的比赛,所有牛从同一起点,以不同的速度开始跑。直到当跑得最快的那一头牛跑完 l 圈时,所有牛才同时停下。

约翰发现在跑圈过程中发生了几次“超越事件”。其定义是:在比赛结束前某时刻,奶牛 x 已经超越了奶牛 y 整整一圈,则称做一次“超越事件”。(注: 至少一圈 ,超越了1/2圈,或者超越了1/4圈等等都不算。且对于同一对奶牛(x,y)不会重复计算次数。)

约翰想知道比赛过程中发生了多少次“超越事件”。

(注:可能原文章表达有误或某些其他原因,各种翻译方式过来的题意都有问题,给人误导很大,这里是根据题目数据和样例解释写的正确的题意,而不是原文)

输入格式:

第一行:三个整数:n,l,c(1 <= l,c <= 25,000)

第二行到第 n+1 行:每行一个整数 vi ,表示奶牛i的速度(1 <= vi <= 1,000,000)

输出格式:

第一行:一个整数,表示总共发生的“超越事件”的次数

证明

t = L * c / v_max

vi * t - vj * t >= c * x // x 为套圈次数
n = (vi - vj) * L / v_max (下取整)
n = (vi * L / v_max) - (vj * L / v_max ) (条件:(vi*L % v_max) >= (vj*L % v_max))
在整体上求出 L * vi % v_max 的逆序对数减去

struct Node{
    long long dat, nam;
}b[100001];
long long N, L, C, v[100001], max_v, tr[100001];
long long new_v[100001], sum[100001], ans, nxd;

bool read(long long &x)
{
    x = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') {
        x = x*10 + ch - '0';
        ch = getchar();
    }
    return x;
}
bool cmp(long long a, long long b) { return a < b; }
bool cmp2(long long a, long long b) { return a < b; }
bool cmp3(Node a, Node b){ 
    if (a.dat > b.dat) return true;
    if (a.dat == b.dat && a.nam > b.nam) return true;
    return false;
}

long long sum_x(long long x)
{
    long long re = 0;
    while (x){
        re += tr[x];
        x -= (x&-x);
    }
    return re;
}

void add(long long x, long long val)
{
    while (x<=N){
        tr[x] += val;
        x += (x&-x);
    }
}
int main()
{
    read(N); read(L); read(C);
    for (long long i=1; i<=N; i++){
        read(v[i]);
        max_v = max(max_v, v[i]);
    }
    sort(v+1,v+N+1,cmp2);
    for (long long i=1; i<=N; i++){
        new_v[i] = (long long) ((L * v[i]) / max_v);
        sum[i] = sum[i-1] + new_v[i];
    }
    for (long long i=N; i; i--){
        ans = ans + (i-1)*new_v[i] - sum[i-1];  
    }

    for (long long i=1; i<=N; i++){
        b[i].dat = ((v[i]*L) % max_v);
        b[i].nam = i;
    }             

    sort(b+1, b+N+1, cmp3);
    for (long long i=1; i<=N; i++){
        long long pos = b[i].nam;
        nxd += sum_x(pos-1);
        add(pos, 1);
    }
    cout<<ans-nxd<<endl;
}
相关标签: n