题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=117
解题思路:所谓逆序就是当前位置的数前面有几个大于这个数,并且这个数与前面数的顺序无关。
归并排序过程中,将序列分为左右两个进行分治,而且是先对左边进行排序。
将左序列中小于右序列中的数填入新序列中,每次遇到右边数小于左边数的时候,总是累计左边数的数量,这样求出的就是所有逆序数的和了。并且如果建立一个逆序数数组们可以得到每个数的逆序数。
01.
#include<iostream>
02.
#include<stdio.h>
03.
using
namespace
std;
04.
int
a[1000010];
05.
int
b[1000010];
06.
long
long
sum=0;
07.
void
marge(
int
*a,
int
beg,
int
end,
int
*b){
08.
if
(beg==end)
return
;
09.
int
mid=(beg+end)/2;
10.
marge(a,beg,mid,b);
11.
marge(a,mid+1,end,b);
12.
int
i=beg,j=mid+1,pos=beg;
13.
while
(i<=mid&&j<=end){
14.
while
(a[i]<=a[j]&&i<=mid)
15.
b[pos++]=a[i++];
16.
while
(a[j]<a[i]&&j<=end){
17.
b[pos++]=a[j++];
18.
sum+=mid+1-i;
19.
}
20.
}
21.
while
(i<=mid)b[pos++]=a[i++];
22.
while
(j<=end)b[pos++]=a[j++];
23.
for
(
int
i=beg;i<=end;i++)
24.
a[i]=b[i];
//回写到a中
25.
}
26.
int
main()
27.
{
28.
int
n;cin>>n;
29.
while
(n--){
30.
sum=0;
31.
int
m;cin>>m;
32.
for
(
int
i=1;i<=m;i++)
33.
scanf
(
"%d"
,&a[i]);
34.
marge(a,1,m,b);
35.
printf
(
"%lld\n"
,sum);
36.
}
37.
return
0;
38.
}