题意就是求逆序数,这题在刘汝佳白书上有一模一样的题,前几天看的,顺便找了下题目,今天回忆了一下写了这个题。归并排序的思想还是很神奇的。为什么排序了还可以求逆序数,因为是用递归,比如3427 1对于右边1的逆序数是4,而左边进行排序变成 2347 1.对于右边的1逆序数还是4,所以只用求局部子逆序数再求大的就可以了。分治法3步还是很经典的:1。划分子问题,2。递归解决子问题,3。合并子问题的解得到原问题的解。
AC代码
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
using namespace std;
#define ll long long
ll a[500001],t[500001];
ll cnt;
void mergesort(ll *a, int x, int y)
{
int m = x+(y-x)/2;
int p = x, i = x, q = m;
if(y-x>1)
{
mergesort(a,x,m);
mergesort(a,m,y);
while(p < m || q < y)
{
if(q >= y || (p < m && a[q] >= a[p])) t[i++] = a[p++];
else
{
cnt += m-p;
t[i++] = a[q++];
}
}
for(i = x; i < y; i++)
a[i] = t[i];
}
}
int main()
{
// freopen("input.txt","r",stdin);
int i,j,t;
while(~scanf("%d",&t) && t)
{
cnt = 0;
for(i = 0; i < t; i++)
scanf("%lld",&a[i]);
mergesort(a,0,t);
printf("%lld\n",cnt);
}
return 0;
}