题目描述 Description
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
输入输出格式 Input/output
输入格式:
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。
输出格式:
给定序列中逆序对的数目。
输入输出样例 Sample input/output
样例测试点#1
输入样例:
6
5 4 2 6 3 1
输出样例:
11
说明 description
对于50%的数据,n≤2500
对于100%的数据,n≤40000。
分析:传统方法是树状数组,但是蒟蒻打起来比较困难,于是直接上归并排序。在合并的时候记录一下逆序对个数就好了。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using namespace std; int n,a[40001],h[40001],ans; int read() //读入优化。 { char c=getchar(); int a=0; while (c<‘0‘||c>‘9‘) c=getchar(); while (c>=‘0‘&&c<=‘9‘) { a=a*10+c-‘0‘; c=getchar(); } return a; } void merge_sort(int l,int r) { if (l==r) return; int mid=(l+r)>>1; merge_sort(l,mid); merge_sort(mid+1,r); int left=l,right=mid+1; for (int i=l;i<=r;i++) if ((a[left]<a[right]||right>r)&&left<=mid) { h[i]=a[left]; left++; } else { h[i]=a[right]; right++; ans+=(mid-left+1); //记录逆序对个数 } for (int i=l;i<=r;i++) a[i]=h[i]; } int main() { n=read(); for (int i=1;i<=n;i++) a[i]=read(); merge_sort(1,n); printf("%d",ans); return 0; }
时间: 2024-10-06 21:43:45