1. 程式人生 > 實用技巧 >AcWing 107 超快速排序 (歸併排序求逆序對)

AcWing 107 超快速排序 (歸併排序求逆序對)

https://www.acwing.com/problem/content/109/

歸併排序求逆序對模板題
每次合併的時候,對答案的貢獻即為在當前左邊區間元素被排序之前先被排序的右邊區間元素的數量

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;

const int maxn = 500010;

int n; ll ans;
int a[maxn], b[maxn];

void Merge(int l, int r, int mid){
	int i = l, j = mid + 1, pos = l;
	for(;i <= mid && j <= r;){
		if(a[i] <= a[j]){
			b[pos++] = a[i++];
			ans += j - (mid + 1);
		}else {
			b[pos++] = a[j++];
		}
	}
	while(i <= mid){
		b[pos++] = a[i++];
		ans += r - (mid + 1) + 1;
	}
	while(j <= r) b[pos++] = a[j++];
	
	for(i = l; i <= r; ++i) a[i] = b[i];
}

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);
	Merge(l,r,mid);
}

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
	while(1){
		n = read(); ans = 0;
		if(n == 0) break;
		
		for(int i=1;i<=n;++i) a[i] = read();
		
		Merge_Sort(1,n);
		
		printf("%lld\n",ans); 
	}
	return 0;
}