https://vjudge.net/problem/poj-1804
这题也可以用树状数组来做的;想到归并排序求逆序对,也是一种方法,随便说说归并排序:
归并排序是把要排序的数组分成两个部分进行排序,然后将两个部分进行归并,然后在合并的时候因为两个部分都是有序的,所以当a[i] > a[j]的时候,因为i后面的数都不小于a[i],所以后面的数自然也大于a[j],所以加上的是mid - i + 1的逆序对;
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn = 1000 + 10;
int a[maxn];
int ans;
void merge(int l,int r)
{
int mid = (l + r) >> 1;
int i = l;
int j = mid + 1;
int temp[maxn];
int k = l;
while(i <= mid && j <= r)
{
if(a[i] > a[j])
{
temp[k ++] = a[j ++];
ans += mid - i + 1;//因为前半部分已经排好序了,后面的数都比这个数大
}
else
{
temp[k ++] = a[i ++];
}
}
while(i <= mid)
{
temp[k ++] = a[i ++];
}
while(j <= r)
{
temp[k ++] = a[j ++];
}
for(i = l; i <= r; i ++)
{
a[i] = temp[i];
}
}
void merge_sort(int l,int r)
{
if(l == r)
return ;
int mid = (l + r) >> 1;
merge_sort(l ,mid);
merge_sort(mid + 1,r);
merge(l,r);
}
int main()
{
int Tcase;
scanf("%d",&Tcase);
for(int ii = 1; ii <= Tcase; ii ++)
{
ans = 0;
int n;
scanf("%d",&n);
for(int i = 1; i <= n; i ++)
scanf("%d",&a[i]);
merge_sort(1,n);
// for(int i = 1; i <= n; i ++)
// cout << a[i] << " ";
// cout << endl;
cout << "Scenario #"<<ii << ":" << endl;
cout << ans << endl << endl;
}
return 0;
}