//428K 0MS G++ mergeSort
#include <cstdio>
#include <cstring>
#include <cstdlib>
char str1[110];
char str2[110];
char tmp1[110];
char tmp2[110];
char strs[110][110];
struct StrInfo{
int reverseOrderNum;
int pos;
} strInfos[110];
typedef struct StrInfo StrInfo;
int comp(const void * a,const void * b) {
return (*(StrInfo*)a).reverseOrderNum
- (*(StrInfo*)b).reverseOrderNum;
}
int MergeSort(char * array, int begin, int end) {
// printf("%d %d\n", begin ,end);
if (begin == end) {
return 0;
}
int totalReverseOrderNum = 0;
int mid = (begin + end)>>1;
int leftPartReverseOrderNum = MergeSort(array, begin, mid);
int rightPartReverseOrderNum = MergeSort(array, mid + 1, end);
totalReverseOrderNum += leftPartReverseOrderNum;
totalReverseOrderNum += rightPartReverseOrderNum;
memset(tmp1, 0, sizeof(tmp1));
memset(tmp2, 0, sizeof(tmp2));
// printf("P1 %d %d\n", mid - begin + 1, end - (mid + 1) + 1);
memcpy(tmp1, array + begin, mid - begin + 1);
memcpy(tmp2, array + mid + 1, end - (mid + 1) + 1);
// printf("STR1: %s STR2: %s\n", tmp1, tmp2);
int leftIndex = 0;
int rightIndex = 0;
int index = begin;
while(tmp1[leftIndex] && tmp2[rightIndex]) {
if (tmp1[leftIndex] <= tmp2[rightIndex]) {
// printf("%c < %c\n", tmp1[leftIndex], tmp2[rightIndex]);
array[index] = tmp1[leftIndex];
leftIndex++;
} else {
array[index] = tmp2[rightIndex];
// printf("%c >= %c %d %d\n", tmp1[leftIndex], tmp2[rightIndex], leftIndex, rightIndex);
totalReverseOrderNum += mid - begin + 1 - leftIndex;
rightIndex++;
}
index++;
}
while(tmp1[leftIndex]) {
array[index++] = tmp1[leftIndex++];
}
while(tmp2[rightIndex]) {
array[index++] = tmp2[rightIndex++];
}
// memset(tmp1, 0, sizeof(tmp1));
// memcpy(tmp1, array + begin, end - begin + 1);
// printf("FINAL: %s\n", tmp1);
return totalReverseOrderNum;
}
int InversionNumber(char* s, int len)
{
int ans=0; //s逆序数
int A,C,G; //各个字母出现次数,T是最大的,无需计算T出现次数
A=C=G=0;
for(int i=len-1;i>=0;i--)
{
switch(s[i])
{
case 'A':A++;break; //A是最小的,无逆序数
case 'C':
{
C++;
ans+=A; //当前C后面出现A的次数就是这个C的逆序数
break;
}
case 'G':
{
G++;
ans+=A;
ans+=C;
break;
}
case 'T':
{
ans+=A;
ans+=C;
ans+=G;
break;
}
}
}
return ans;
}
int getReverseOrderNum(char * str) {
memcpy(str2, str, strlen(str) + 1);
// printf("%s\n", str2);
int res = MergeSort(str2, 0, strlen(str2) - 1);
// printf("%s\n", str2);
// int res = InversionNumber(str2, strlen(str2));
return res;
}
int length;
int strNum;
int main() {
while(scanf("%d %d", &length, &strNum) != EOF) {
for (int i = 0; i < strNum; i++) {
scanf("%s", strs[i]);
strInfos[i].pos = i;
strInfos[i].reverseOrderNum = getReverseOrderNum(strs[i]);
// strInfos[i].reverseOrderNum = InversionNumber(strs[i], strlen(strs[i]));
// printf("%d\n", strInfos[i].reverseOrderNum);
}
qsort(strInfos, strNum, sizeof(StrInfo), comp);
for (int i = 0; i < strNum; i++) {
printf("%s\n", strs[strInfos[i].pos]);
}
}
}
MLGB,strInfos数组开小了,WA了好几次
算是一道很好的基础题,因为这道题可以是归并排序和快速排序的综合题,
首先要用归并排序(也可以树状数组,线段树,不过归并最接地气)求出每个字符串的逆序数(在这里犯了好多细节错误,以后要好好理理, 并且因为本题的特殊性,只有四种字母,因此可以用o(n)方法来求,写起来简单些,虽然不算快), 然后就是快速排序(不想写了,直接qsort)将逆序数俺从小到大排,输出对应的字符串就可以。