//P1908 逆序对 #include<bits/stdc++.h> using namespace std; int a[500005]; int tmp[500005]; long long ans=0; void mergesort(int l,int r) { if(l==r) return; int mid=(l+r)>>1; mergesort(l,mid);mergesort(mid+1,r); int i=l,j=mid+1,tot=l-1; while(j<=r&&i<=mid) { if(a[i]<=a[j]) tmp[++tot]=a[i++]; else tmp[++tot]=a[j++],ans+=(mid-i+1); } while(i<=mid) tmp[++tot]=a[i++]; while(j<=r) tmp[++tot]=a[j++]; for(int i=l;i<=r;i++) a[i]=tmp[i]; } int main() { int n;scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); mergesort(1,n); printf("%lld",ans); return 0; }
直接暴力求的话,显然时间复杂度是不可接受的 我们不妨转换一下,分而治之 把整个数列劈成两半 则总的逆序对数量=左半部分逆序对数量+右半部分逆序对数量+左边的数比右边大的对数 前两项我们可以递归求解,最后一项我们可以在归并排序的同时稍加处理,O(N)计算出来 这样时间复杂度与归并排序一样,都是O(NlogN)的