题目链接:http://202.121.199.212/JudgeOnline/problem.php?cid=1130&pid=9
题目大意 & Input & Output &Sample Input/Output 请ctrl-c+ctrl-v点开上述链接(真的不是我懒)
题解
然后因为这道题题目有点水,强行遍历也能过,但是看了朋友用归并写,自己也写了一个,也可以当归并排序模板来用。
首先,归并是一个n*log(n)的排序算法,比普通的遍历n*n要节省时间。
然后归并的原理就是假设有已经排序好了的两个数组a[n],b[n](从小到大),我们再申请一个空的数组c[n]。
将两个数组都从a[j],b[k](j=0,k=0)第一个开始比较,将小的那一个放在c[i] (i=0)。
假设a[0]<b[0],那就算c[0]=a[0],j++,i++,k不变。
依次比较,当a数组或b数组都比完了之后,将另一个多出的数组的元素放入到c中就可以了。
例子 a:1345 b:239
c:1----c:12----c:123----c:1233----c:12334----c:123345----c:1233459
函数代码是这样的( Rep2(x,y,z) 就是 for(int x=y;x<=z;++x) ):
void ME(int l,int m,int r)
{
int i=l;
int k=l;
int j=m+1;
while( i<=m && j<=r)
{
if(a[i]>a[j])
{
count1+=(m-i+1);
ans[k++]=a[j++];
}
else {
ans[k++]=a[i++];
}
}
while(i<=m)ans[k++]=a[i++];
while(j<=r)ans[k++]=a[j++];
Rep2(i,l,r)a[i]=ans[i];
}
题目AC代码
/* shuoj 1811
测试结果 AC
BY SHU_ONISAC
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
#define INF 0x3FFFFFFF;
#define Rep(x,n) for(int x=0;x<n;++x)
#define Rep2(x,l,n) for(int x=l;x<=n;++x)
typedef long long ll;
const int MAXN = 1010;
int a[MAXN],ans[MAXN];
int count1;
void ME(int l,int m,int r)
{
int i=l;
int k=l;
int j=m+1;
while( i<=m && j<=r)
{
if(a[i]>a[j])
{
count1+=(m-i+1);
ans[k++]=a[j++];
}
else {
ans[k++]=a[i++];
}
}
while(i<=m)ans[k++]=a[i++];
while(j<=r)ans[k++]=a[j++];
Rep2(i,l,r)a[i]=ans[i];
}
void MS(int l,int r)//merge sort
{
if(l<r)
{
int m=(l+r) >> 1;
MS(l,m);
MS(m+1,r);
ME(l,m,r);
}
}
int main()
{
int n;
int cns=1;
while(cin>>n)
{
count1=0;
Rep(i,n)cin>>a[i];
MS(0,n-1);
printf("Case %d:\n",cns++);
cout<<count1<<endl;
//Rep(i,n)cout<<a[i];
//cout<<endl;
}
return 0;
}