参考资料: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)