归并排序,就是将两个有序的子序列进行排序。具体参考https://www.cnblogs.com/chengxiao/p/6194356.html。
题目描述
猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。
最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ai>aja_i>a_jai>aj 且 i<ji<ji<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。
Update:数据已加强。
输入格式
第一行,一个数 nnn,表示序列中有 nnn个数。
第二行 nnn 个数,表示给定的序列。序列中每个数字不超过 10910^9109。
输出格式
输出序列中逆序对的数目。
输入输出样例
输入 #1
6 5 4 2 6 3 1
输出 #1
11
说明/提示
对于 25%25\%25% 的数据,n≤2500n leq 2500n≤2500
对于 50%50\%50% 的数据,n≤4×104n leq 4 imes 10^4n≤4×104。
对于所有数据,n≤5×105n leq 5 imes 10^5n≤5×105
请使用较快的输入输出
应该不会 O(n2)O(n^2)O(n2) 过 50 万吧 by chen_zhe
题解:
#include<bits/stdc++.h> using namespace std; int n; int a[500005],s[500005]; long long int ans; inline int read(){ char ch=getchar(); int f=1; int x=0; while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } void msort(int l,int r){ if(l==r)return ; int mid=(l+r)>>1; msort(l,mid); msort(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid&&j<=r){ if(a[i]<=a[j])s[k++]=a[i++]; else{ s[k++]=a[j++]; ans+=mid-i+1; } } while(i<=mid){ s[k++]=a[i++]; } while(j<=r)s[k++]=a[j++]; for(int i=l;i<=r;i++)a[i]=s[i]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)a[i]=read(); msort(1,n); printf("%lld ",ans); }