时间限制: 1000 ms 内存限制: 65536 kb
总通过人数: 234 总提交人数: 340
题目描述
输入一个正整数n,随后给出一个长度为n的整数序列a1,a2,a3...an。求给定序列的逆序数。
概念回顾:
逆序对:数列a[1],a[2],a[3]…中的任意两个数a[i],aj,如果a[i]>a[j],那么我们就说这两个数构成了一个逆序对。
逆序数:一个数列中逆序对的总数。
输入
多组测试数据。对于每组测试数据,给出序列长度n,和一个长度为n的序列a1,a2,a3...an
(0<n<=10^6,保证ai在int范围内)
输出
对于每组数据,输出该序列的逆序数。
输入样例
7
3 5 4 8 2 6 9
输出样例
6
Hint
1、用n^2的算法是不行不行滴╮(╯_╰)╭
2、分治法
题解
OIers都知道这题的意思就是用归并排序求逆序对。
不过我WA了两次,最后发现ans不能用int来存……坑。
代码
#include<iostream> #include<cstdlib> #include<cstdio> using namespace std; int a[1000005],b[1000005]; long long ans; void merge_sort(int l,int r) { if (l==r) return; int mid=(l+r)/2; merge_sort(l,mid); merge_sort(mid+1,r); int i=l,j=mid+1,k=l; while (i<=mid && j<=r) { if (a[i]<=a[j]) b[k++]=a[i++]; else { b[k++]=a[j++]; ans+=mid-i+1; } } while (i<=mid) b[k++]=a[i++]; while (j<=r) b[k++]=a[j++]; for (int t=l; t<=r; ++t) a[t]=b[t]; } int main() { int n; while (scanf("%d",&n)!=EOF) { ans=0; for (int i=1; i<=n; i++) scanf("%d",&a[i]); merge_sort(1,n); printf("%lld\n",ans); } return 0; }