1. 程式人生 > 實用技巧 >USACO20OPEN Haircut G

USACO20OPEN Haircut G

題目連結

Solution

不會做,於是參考題解

假設現在 \(\mathrm{John}\) 不再需要為肆意生長的頭髮而煩惱了,而是成為了一個因禿頭而抓狂的脫髮人士。現在,我們把理髮看成是生髮,那麼第 \(i\) 根頭髮的極限長度就是 \(a_i\).

頭髮從 \(0\) 開始生長,在到達極限長度之前,每秒生長 \(1\) 個單位長度。現在我們把題目中的 \(j\) 看成是時間,那麼第 \(j\) 秒頭髮最長一定不會超過 \(j\). 這不是正好符合題目限制嗎?

顯而易見的,第 \(0\) 秒的逆序對個數是 \(0\). 那麼,我們現在需要考慮的是第 \(j\)新增的逆序對。

Code

#include <iostream>
#include <cstdio>
#include <cstring>
#define LL long long
#define lowbit(x) (x & (-x))
using namespace std;

const int N = 2333333;
LL n, a[N], sum[N], t[N];

void add(LL x) { while(x <= n + 1) t[x]++, x += lowbit(x); }
LL query(LL x)
{
    LL res = 0;
    while(x) res += t[x], x -= lowbit(x);
    return res;
}

int main()
{
    scanf("%lld", &n);
    memset(t, 0, sizeof(t));
    memset(sum, 0, sizeof(sum));
    for(int i = 1; i <= n; i++)
    {
        scanf("%lld", &a[i]), a[i]++;
        sum[a[i] + 1] += query(n + 1) - query(a[i]);
        add(a[i]);
    }
    for(int i = 1; i <= n; i++)
    {
        sum[i] += sum[i - 1];
        printf("%lld\n", sum[i]);
    }
    return 0;
}