归并排序

归并排序

1、二分归并排序可以算出一个数组中的逆序对数目,因为本身这个算法利用的就是分治算法,所以可以在 \(nlogn\) 的时间复杂度里面求出所有逆序对数目。

2、另外我还拓展了一些三分归并、四分归并...等等,目前没发现有啥用途,然后我又写了个代码,支持最多 \(31\) 分归并排序,通过这个代码测试,可以发现六分归并在所有归并中是最快的,个人测试,正确性不保证$。

template<typename T>
struct Gb{
	vector<T> c, d;
	Gb(int n) : c(n + 1), d(n + 1) {}
	
	// 二分归并排序(可求逆序对数目)
	inline T Msort2(int l, int r, vector<T> &a) {
		T ans{};
		if (l == r) return ans;
		int mid = (l + r) >> 1;
		int i = l, j = mid + 1, cnt = l;
		ans += Msort2(l, mid, a); ans += Msort2(j, r, a);
		while (i <= mid && j <= r) {
			if (a[i] <= a[j]) c[cnt++] = a[i++];
			else c[cnt++] = a[j++], ans += (mid - i + 1);
		}
		
		while (i <= mid) c[cnt++] = a[i++];
		while (j <= r) c[cnt++] = a[j++];
		
		for (int k = l; k <= r; k++) a[k] = c[k];
		return ans;
	}
	
	// 三分归并排序(用途未知)
	inline void Msort3(int l, int r, vector<T> &a) {
		int len = r - l + 1;
		if (len <= 2) {
			d[l] = min(a[l], a[r]);
			d[r] = max(a[l], a[r]);
			for (int i = l; i <= r; i++) a[i] = d[i];
			return;
		}
		
		int l1 = l, l2 = l1 + (len / 3), l3 = l2 + (len / 3), r1 = l2 - 1, r2 = l3 - 1, r3 = r, cnt = l;
		Msort3(l1, r1, a); Msort3(l2, r2, a); Msort3(l3, r3, a);
		while (l1 <= r1 && l2 <= r2 && l3 <= r3) {
			if (a[l1] <= a[l2] && a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		
		while (l1 <= r1 && l2 <= r2) {
			if (a[l1] <= a[l2]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l2++];
		}
		while (l1 <= r1 && l3 <= r3) {
			if (a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l3++];
		}
		while (l2 <= r2 && l3 <= r3) {
			if (a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		
		while (l1 <= r1) d[cnt++] = a[l1++];
		while (l2 <= r2) d[cnt++] = a[l2++];
		while (l3 <= r3) d[cnt++] = a[l3++];
		
		for (int i = l; i <= r; i++) a[i] = d[i];
	}
	
	// 四分归并排序(用途未知)
	inline void Msort4(int l, int r, vector<T> &a) {
		if (r - l + 1 <= 3) {
			for (int i = l + 1; i <= r; i++) {
				T t = a[i];
				int j = i - 1;
				while (j >= l && t < a[j]) {
					a[j + 1] = a[j];
					j--;
				}
				a[j + 1] = t;
			}
			return;
		}
		
		int len = r - l + 1;
		int l1 = l, l2 = l1 + (len / 4), l3 = l2 + (len / 4), l4 = l3 + (len / 4), r1 = l2 - 1, r2 = l3 - 1, r3 = l4 - 1, r4 = r, cnt = l;
		Msort4(l1, r1, a); Msort4(l2, r2, a); Msort4(l3, r3, a); Msort4(l4, r4, a);
		while (l1 <= r1 && l2 <= r2 && l3 <= r3 && l4 <= r4) {
			if (a[l1] <= a[l2] && a[l1] <= a[l3] && a[l1] <= a[l4]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l3] && a[l2] <= a[l4]) d[cnt++] = a[l2++];
			else if (a[l3] <= a[l1] && a[l3] <= a[l2] && a[l3] <= a[l4]) d[cnt++] = a[l3++];
			else d[cnt++] = a[l4++];
		}
		
		while (l1 <= r1 && l2 <= r2 && l3 <= r3) {
			if (a[l1] <= a[l2] && a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		while (l1 <= r1 && l2 <= r2 && l4 <= r4) {
			if (a[l1] <= a[l2] && a[l1] <= a[l4]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l4]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l4++];
		}
		while (l1 <= r1 && l4 <= r4 && l3 <= r3) {
			if (a[l1] <= a[l4] && a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else if (a[l4] <= a[l1] && a[l4] <= a[l3]) d[cnt++] = a[l4++];
			else d[cnt++] = a[l3++];
		}
		while (l4 <= r4 && l2 <= r2 && l3 <= r3) {
			if (a[l4] <= a[l2] && a[l4] <= a[l3]) d[cnt++] = a[l4++];
			else if (a[l2] <= a[l4] && a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		
		while (l1 <= r1 && l2 <= r2) {
			if (a[l1] <= a[l2]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l2++];
		}
		while (l1 <= r1 && l3 <= r3) {
			if (a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l3++];
		}
		while (l1 <= r1 && l4 <= r4) {
			if (a[l1] <= a[l4]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l4++];
		}
		while (l2 <= r2 && l3 <= r3) {
			if (a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		while (l2 <= r2 && l4 <= r4) {
			if (a[l2] <= a[l4]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l4++];
		}
		while (l3 <= r3 && l4 <= r4) {
			if (a[l3] <= a[l4]) d[cnt++] = a[l3++];
			else d[cnt++] = a[l4++];
		}
		
		while (l1 <= r1) d[cnt++] = a[l1++];
		while (l2 <= r2) d[cnt++] = a[l2++];
		while (l3 <= r3) d[cnt++] = a[l3++];
		while (l4 <= r4) d[cnt++] = a[l4++];
		
		for (int i = l; i <= r; i++) a[i] = d[i];
	}
};

void solve() {
//	int n;
//	read(n);
//	vector<i64> a(n + 1);
//	for (int i = 1; i <= n; i++) read(a[i]);
//	Gb<i64> t(n);
//	cout << t.Msort2(1, n, a) << '\n';
	
//	int n;
//	read(n);
//	vector<i64> a(n + 1);
//	for (int i = 1; i <= n; i++) read(a[i]);
//	Gb<i64> t(n);
//	t.Msort3(1, n, a);
//	for (int i = 1; i <= n; i++) cout << a[i] << ' ';
}

多分归并排序:

template<typename T>
struct Gb{
	vector<T> c, d;
	Gb(int n) : c(n + 1), d(n + 1) {}
	
	// 二分归并排序(可求逆序对数目)
	inline T Msort2(int l, int r, vector<T> &a) {
		T ans{};
		if (l == r) return ans;
		int mid = (l + r) >> 1;
		int i = l, j = mid + 1, cnt = l;
		ans += Msort2(l, mid, a); ans += Msort2(j, r, a);
		while (i <= mid && j <= r) {
			if (a[i] <= a[j]) c[cnt++] = a[i++];
			else c[cnt++] = a[j++], ans += (mid - i + 1);
		}
		
		while (i <= mid) c[cnt++] = a[i++];
		while (j <= r) c[cnt++] = a[j++];
		
		for (int k = l; k <= r; k++) a[k] = c[k];
		return ans;
	}
	
	// 三分归并排序(用途未知)
	inline void Msort3(int l, int r, vector<T> &a) {
		int len = r - l + 1;
		if (len <= 2) {
			d[l] = min(a[l], a[r]);
			d[r] = max(a[l], a[r]);
			for (int i = l; i <= r; i++) a[i] = d[i];
			return;
		}
		
		int l1 = l, l2 = l1 + (len / 3), l3 = l2 + (len / 3), r1 = l2 - 1, r2 = l3 - 1, r3 = r, cnt = l;
		Msort3(l1, r1, a); Msort3(l2, r2, a); Msort3(l3, r3, a);
		while (l1 <= r1 && l2 <= r2 && l3 <= r3) {
			if (a[l1] <= a[l2] && a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		
		while (l1 <= r1 && l2 <= r2) {
			if (a[l1] <= a[l2]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l2++];
		}
		while (l1 <= r1 && l3 <= r3) {
			if (a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l3++];
		}
		while (l2 <= r2 && l3 <= r3) {
			if (a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		
		while (l1 <= r1) d[cnt++] = a[l1++];
		while (l2 <= r2) d[cnt++] = a[l2++];
		while (l3 <= r3) d[cnt++] = a[l3++];
		
		for (int i = l; i <= r; i++) a[i] = d[i];
	}
	
	// 四分归并排序(用途未知)
	inline void Msort4(int l, int r, vector<T> &a) {
		if (r - l + 1 <= 3) {
			for (int i = l + 1; i <= r; i++) {
				T t = a[i];
				int j = i - 1;
				while (j >= l && t < a[j]) {
					a[j + 1] = a[j];
					j--;
				}
				a[j + 1] = t;
			}
			return;
		}
		
		int len = r - l + 1;
		int l1 = l, l2 = l1 + (len / 4), l3 = l2 + (len / 4), l4 = l3 + (len / 4), r1 = l2 - 1, r2 = l3 - 1, r3 = l4 - 1, r4 = r, cnt = l;
		Msort4(l1, r1, a); Msort4(l2, r2, a); Msort4(l3, r3, a); Msort4(l4, r4, a);
		while (l1 <= r1 && l2 <= r2 && l3 <= r3 && l4 <= r4) {
			if (a[l1] <= a[l2] && a[l1] <= a[l3] && a[l1] <= a[l4]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l3] && a[l2] <= a[l4]) d[cnt++] = a[l2++];
			else if (a[l3] <= a[l1] && a[l3] <= a[l2] && a[l3] <= a[l4]) d[cnt++] = a[l3++];
			else d[cnt++] = a[l4++];
		}
		
		while (l1 <= r1 && l2 <= r2 && l3 <= r3) {
			if (a[l1] <= a[l2] && a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		while (l1 <= r1 && l2 <= r2 && l4 <= r4) {
			if (a[l1] <= a[l2] && a[l1] <= a[l4]) d[cnt++] = a[l1++];
			else if (a[l2] <= a[l1] && a[l2] <= a[l4]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l4++];
		}
		while (l1 <= r1 && l4 <= r4 && l3 <= r3) {
			if (a[l1] <= a[l4] && a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else if (a[l4] <= a[l1] && a[l4] <= a[l3]) d[cnt++] = a[l4++];
			else d[cnt++] = a[l3++];
		}
		while (l4 <= r4 && l2 <= r2 && l3 <= r3) {
			if (a[l4] <= a[l2] && a[l4] <= a[l3]) d[cnt++] = a[l4++];
			else if (a[l2] <= a[l4] && a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		
		while (l1 <= r1 && l2 <= r2) {
			if (a[l1] <= a[l2]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l2++];
		}
		while (l1 <= r1 && l3 <= r3) {
			if (a[l1] <= a[l3]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l3++];
		}
		while (l1 <= r1 && l4 <= r4) {
			if (a[l1] <= a[l4]) d[cnt++] = a[l1++];
			else d[cnt++] = a[l4++];
		}
		while (l2 <= r2 && l3 <= r3) {
			if (a[l2] <= a[l3]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l3++];
		}
		while (l2 <= r2 && l4 <= r4) {
			if (a[l2] <= a[l4]) d[cnt++] = a[l2++];
			else d[cnt++] = a[l4++];
		}
		while (l3 <= r3 && l4 <= r4) {
			if (a[l3] <= a[l4]) d[cnt++] = a[l3++];
			else d[cnt++] = a[l4++];
		}
		
		while (l1 <= r1) d[cnt++] = a[l1++];
		while (l2 <= r2) d[cnt++] = a[l2++];
		while (l3 <= r3) d[cnt++] = a[l3++];
		while (l4 <= r4) d[cnt++] = a[l4++];
		
		for (int i = l; i <= r; i++) a[i] = d[i];
	}

    // n分归并排序(用途未知,2<=n<=30)
    inline void EXsort(int l, int r, vector<T> &a, const int path_num) {
        T ans = 0ll;
        int len = r - l + 1;
        T *ptr = a.data();
        if (len < path_num) {
            for (int i = l + 1; i <= r; i++) {
                T t = ptr[i];
                int j = i - 1;
                while (j >= l && t < ptr[j]) {
                    ptr[j + 1] = ptr[j];
                    j--;
                }
                ptr[j + 1] = t;
            }
            return;
        }
        
        static int dep = -1;
        static int bak[64][32];
        int *L = *(bak + ++dep), *R = *(bak + ++dep);
        L[0] = l;
        for (int i = 1; i < path_num; i++) L[i] = L[i - 1] + len / path_num;
        R[path_num - 1] = r;
        for (int i = path_num - 2; i >= 0; i--) R[i] = L[i + 1] - 1;
        for (int i = 0; i < path_num; i++) EXsort(L[i], R[i], a, path_num);
        
        int cnt = l;
        int s = (1 << path_num) - 1;
        while (s) {
            int i = s;
            int mx = __lg(i & -i);
            i -= i & -i;
            while (i) {
                int j = i & -i, k = __lg(j);
                if (ptr[L[mx]] > ptr[L[k]]) {
                    mx = k;
                }
                i -= j;
            }
            d[cnt++] = ptr[L[mx]];
            if (++L[mx] > R[mx]) {
                s &= ~(1 << mx);
            }
        }
        
        dep -= 2;
        for (int i = l; i <= r; i++) ptr[i] = d[i];
    }
};


void solve() {
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    Gb<int> gb(n);
    int fen = 12;
    gb.EXsort(1, n, a, fen);
    for (int i = 1; i < a.size(); i++) cout << a[i] << ' ';
}
posted @ 2024-08-15 02:17  grape_king  阅读(20)  评论(0)    收藏  举报