題目鏈接 洛谷P1908
引用該題題解中的一段話:
//在某個時候,左區間: 5 6 7 下標爲i
// 右區間: 1 2 9 下標爲j
//
//這個時候我們進行合併:
//step 1:由於 5>1,所以產生了逆序對,這裏,我們發現,左區間所有還沒有被合併的數都比 1 大,所以1與左區間所有元素共產生了 3 個逆序對(即tot_numleft-i+1對),統計答案併合並 1
//step 2:由於 5>2,由上產生了3對逆序對,統計答案併合並 2
//step 3:由於 5<9, 沒有逆序對產生,右區間下標 j++
//step 4:由於 6<9, 沒有逆序對產生,右區間下標 j++
//step 5:由於 7<9, 沒有逆序對產生,右區間下標 j++
//step 6:由於右區間已經結束,正常執行合併左區間剩餘,結束
//PS: tot_numleft=3,即左區間總元素個數
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 501000;
ll n,a[maxn],b[maxn];
ll cc(ll l,ll r)
{
if(l>=r)
return 0;
ll mid = (l + r) / 2;
ll ans = 0;
ans+=cc(l, mid);
ans+=cc(mid + 1, r);
ll i, u, v;
for (i = l, u = l, v = mid + 1; i <= r && u <= mid && v <= r; i++)
{
if(a[u]<=a[v])
{
b[i] = a[u];
u++;
}
else
{
ans += mid - u + 1;
b[i] = a[v];
v++;
}
}
if(u<=mid)
{
for (ll j = i; j <= r;j++)
{
b[j] = a[u++];
}
}
if(v<=r)
{
for (ll j = i; j <= r;j++)
b[j] = a[v++];
}
for (ll k = l; k <= r; k++)
a[k]=b[k];
return ans;
}
int main()
{
scanf("%lld", &n);
for (ll i = 1; i <= n; i++)
scanf("%lld", &a[i]);
printf("%lld\n", cc(1, n));
return 0;
}