时间限制:1 秒
内存限制:32 兆
特殊判题:否
提交:2777
解决:656
-
题目描述:
- 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
-
输入:
-
每个测试案例包括两行:第一行包含一个整数n,表示数组中的元素个数。其中1 <= n <= 10^5。第二行包含n个整数,每个数组均为int类型。
-
输出:
- 对应每个测试案例,输出一个整数,表示数组中的逆序对的总数。
-
样例输入:
-
4 7 5 6 4
-
样例输出:
-
5
思路:
看了别人的思路才明白的。
这个题要对数组进行归并排序,排序过程中的操作次数就是逆序对的个数。
注意:全局变量count不能声明为int型,必须为long long型。因为题目中说数组最大为10^5,那么最大逆序对为(10^5-1)*10^5/2,这个数大约在50亿左右,超过了int型的表示范围。 |
代码:
#include <stdio.h>
#define N 100000
void print(int *a, int n)
{
for (int i=0; i<n; i++)
printf("%d ", a[i]);
printf("\n");
}
long long mergeSort(int a[N], int s, int e)
{
if (s == e)
return 0;
long long count;
int m = (s+e)/2;
count = 0;
count += mergeSort(a, s, m);
count += mergeSort(a, m+1, e);
int b[N];
int i, j, k;
i = s;
j = m+1;
k = s;
while (i<=m || j<=e)
{
if (j > e || ( i <= m && a[i] > a[j]))
{
b[k++] = a[i];
count += (e-j+1);
//printf("i,j,m,e=%d,%d,%d,%d count=%lld\n", i,j,m,e,count);
i++;
}
else
{
b[k++] = a[j];
j++;
}
}
//print(a+s, e-s+1);
//printf("s=%d, e=%d, count=%lld\n", s, e, count);
for (i=s; i<=e; i++)
a[i] = b[i];
return count;
}
int main(void)
{
int n, i;
int a[N];
long long count;
while (scanf("%d", &n) != EOF)
{
for(i=0; i<n; i++)
scanf("%d", &a[i]);
/*
count = 0;
for(i=0; i<n; i++)
{
for(j=i+1; j<n; j++)
{
if (a[i] > a[j])
count ++;
}
}
*/
count = mergeSort(a, 0, n-1);
printf("%lld\n", count);
}
return 0;
}
/**************************************************************
Problem: 1348
User: liangrx06
Language: C
Result: Accepted
Time:100 ms
Memory:7864 kb
****************************************************************/