题目大意:给出一组字符串,给这组字符串按逆序对数从小到大排列。
解题思路:按分治类似归并排序算法求出每个字符串的逆序对数,在用快速排序排列
求逆序对数类似poj 2299题
http://blog.csdn.net/xiaoxiaoluo/article/details/7686942
这里注意的是当逆序数相同时,按照字符串原先的相对位置输出。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node
{
int index;
int value;
};
const int maxn = 51;
const int maxm = 101;
char str[maxm][maxn], t[maxn], tmp[maxn];
node result[maxm];
int n, m;
int merge(char *s, int low, int high);
inline bool cmp(const node &a, const node &b)
{
if(a.value == b.value)
return a.index < b.index;
return a.value < b.value;
}
int main()
{
scanf("%d %d", &m, &n);
for(int i = 0; i < n; i++)
{
scanf("%s", str[i]);
strcpy(t, str[i]);
result[i].value = merge(t, 0, m - 1);
result[i].index = i;
}
sort(result, result + n, cmp);
for(int i = 0; i < n; i++)
printf("%s\n", str[result[i].index]);
return 0;
}
int merge(char *s, int low, int high)
{
int su = 0;
if(low < high)
{
int k = 0;
int mid = (low + high) >> 1;
su += merge(s, low, mid);
su += merge(s, mid + 1, high);
int i, j;
for(i = low, j = mid + 1; i <= mid && j <= high; )
{
if(s[i] > s[j])
tmp[k++] = s[j++];
else
{
su += j - mid - 1;
tmp[k++] = s[i++];
}
}
while(i <= mid)
{
tmp[k++] = s[i++];
su += j - mid - 1;
}
while(j <= high)
{
tmp[k++] = s[j++];
}
i = low, j = 0;
while(j < k)
s[i++] = tmp[j++];
}
return su;
}