题目链接 洛谷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;
}