参考资料:http://poj.org/problem?id=2299 原题是求数列逆序数对的个数。
如果数组数据范围很大,而数据数量与之相比小很多,那么直接用输入数据来求逆序数就不值得了,可以进行离散化处理。处理要点是:
1.用一个struct接受数据和一个自定义的序号no,排序时序号也就一起排序了。
2.for遍历数组,no的位置写上i,就完成了离散化。
例如:
struct data
{
int v;
int no;
};
原始数据:100,10,1000,1
直接做的话空间复杂度为1000,
先将其读进来:{v=100,no=0},{v=10,no=1},{v=1000,no=2},{v=1,no=3}
再排序:{v=1, no=3}, {v=10, no=1}, {v=100, no=0}, {v=1000, no=2}
新开一个长度为4的数组,遍历刚才已排序的数据,a[no=3]=1, a[no=1]=2, a[no=0]=3, a[no=2]=4,
即:{3,2,4,1} 与原始的{100,10,1000,1}大小关系一直,空间代价O(n)。
#include <stdio.h>
#include <stdlib.h>
// 树状数组
int lowbit(int x);
int gsum(int *p, int n, int pos);
void modify(int *p, int n, int pos, int value);
// 离散化
typedef struct datano
{
int data;
int no;
}datano;
int cmpdata(const void *p1, const void *p2);
int main()
{
int m;
scanf("%d", &m);
int j = 0;
while (j < m)
{
printf("The %d th test case:\n", j + 1);
// 1.输入
int n;
int *cmdata;
int *smdata;
int s = 0;
int i = 0;
datano *input;
scanf("%d", &n);
input = (datano*) malloc(sizeof(datano) * n);
while(i < n)
{
scanf("%d", &(input[i].data));
input[i].no = i;
i++;
}
// 2.离散化
qsort(input, n, sizeof(datano), cmpdata);
cmdata = (int*)malloc(sizeof(int) * n);
for (i=0; i<n; i++)
{
cmdata[input[i].no] = i + 1;
}
printf("离散化结果:\t(");
for (i=0; i<n; i++)
printf("%d,", input[i].data);
printf(") -> (");
for (i=0; i<n; i++)
printf("%d,", cmdata[i]);
printf(")\n");
free(input);
// 3.计算
smdata = (int*)malloc(sizeof(int) * (n+1));
for (i=0; i<n+1; i++)
smdata[i] = 0;
for (i=0; i<n; i++)
{
modify(smdata, n, cmdata[i], 1);
s += (i + 1 - gsum(smdata, n, cmdata[i]) );
}
free(cmdata);
free(smdata);
printf("total: \t\t%d inverse pair(s)\n", s);
j++;
}
return 0;
}
////////////////////////////
int lowbit(int x)
{
return x & -x;
}
int gsum(int *p, int n, int pos)
{
int s = 0;
int i;
for (i = pos; i>=1; i -= lowbit(i) )
s += p[i];
return s;
}
void modify(int *p, int n, int pos, int value)
{
int i;
for (i = pos; i<=n; i += lowbit(i) )
p[i] += value;
}
int cmpdata(const void *p1, const void *p2)
{
datano *dp1 = (datano *)p1;
datano *dp2 = (datano *)p2;
return dp1->data - dp2->data;
}
input:
4
4
100 10 1 1000
7
1 900 10000 20 -9999 10 100
10
1 2 3 4 5 6 7 8 9 10
4
9 7 4 2
output:
The 1 th test case:
离散化结果: (1,10,100,1000,) -> (3,2,1,4,)
total: 3 inverse pair(s)
The 2 th test case:
离散化结果: (-9999,1,10,20,100,900,10000,) -> (2,6,7,4,1,3,5,)
total: 11 inverse pair(s)
The 3 th test case:
离散化结果: (1,2,3,4,5,6,7,8,9,10,) -> (1,2,3,4,5,6,7,8,9,10,)
total: 0 inverse pair(s)
The 4 th test case:
离散化结果: (2,4,7,9,) -> (4,3,2,1,)
total: 6 inverse pair(s)