题目地址
https://vjudge.net/contest/205706#problem/J
先学习了一下什么是归并排序
http://blog.youkuaiyun.com/yuehailin/article/details/68961304
又学习了一下怎么用归并排序求逆序对
http://blog.youkuaiyun.com/Sugar_Z_/article/details/48213537
于是这道题就把每一个字符串归并排序的同时记录了逆序对个数,然后再用sort函数把字符串按逆序对个数排列。
感觉归并排序求逆序对还挺套路的。但是现在还不太理解。
{3,1,2,6,7,4,8,5}
如果归并排序的话应该是按如下顺序
{1,3},{2,6,7,4,8,5}
{1,3},{2,6},{7,4,8,5}
{1,2,3,6},{7,4,8,5}
{1,2,3,6},{4,7},{8,5}
{1,2,3,6},{4,7},{5,8}
{1,2,3,6},{4,5,7,8}
{1,2,3,4,5,6,7,8}
#include<stdio.h>
#include<algorithm>
using namespace std;
struct node
{
char change[60];
char str[60];
int s;
}dna[110];
bool cmp(node x,node y)
{
return x.s<y.s;
}
void merge(char a[],char t[],int start,int mid,int end,int cnt)
{
int i=start,j=mid+1,k=0;
while(i!=mid+1&&j!=end+1)
{
if(a[i]<=a[j])
{
t[k++]=a[i++];
}
else
{
dna[cnt].s+=mid-i+1;
t[k++]=a[j++];
}
}
while(i<=mid)
{
t[k++]=a[i++];
}
while(j<=end)
{
t[k++]=a[j++];
}
for(i=0;i<k;i++)
{
a[start+i]=t[i];
}
}
void mergesort(char a[],char t[],int start,int end,int cnt)
{
if(start<end)
{
int mid=(start+end)/2;
mergesort(a,t,start,mid,cnt);
mergesort(a,t,mid+1,end,cnt);
merge(a,t,start,mid,end,cnt);
}
}
int main()
{
int m,n;
char temp[60];
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
{
getchar();
scanf("%s",dna[i].str);
}
for(int i=1;i<=n;i++)
{
dna[i].s=0;
strcpy(dna[i].change,dna[i].str);
mergesort(dna[i].change,temp,0,m-1,i);
}
sort(dna+1,dna+n+1,cmp);
for(int i=1;i<=n;i++)
{
printf("%s\n",dna[i].str);
}
}