【瞎搞胡搞】倍增归并

我不知道是否有人之前搞过这种东西

P1177 【模板】快速排序

就是一个...倍增写的归并排序,好像并没有必要

时间复杂度 \(O(n \log_2 n)\),这里的 \(n=2^k\)

如果一个序列长度为 \(m\),则 \(n\) 为最小的 \(2^k \ge m\)

基本思路:
好像没什么可以讲的

实现:
1、用 \(- \infty\) 把序列凑成一个长度 \(2\) 的幂的序列,然后设定步长 \(step = 1\)
2、设指向区间起始点的 \(i = 1\)
3、合并 \(2\) 个序列,第一个为 \(i\) ~ \(i + \dfrac{step}{2} - 1\),第二个为 \(i + \dfrac{step}{2}\) ~ \(i + step - 1\),存到新数组
4、重复执行 \(2\) 步,每次 \(i=i+step\),直到 \(i > m\)
5、赋值回原序列
6、重复执行 \(2\) 步,每次 \(step=2step\),直到 \(step > m\)
7、输出除 \(- \infty\) 的序列

把序列凑成一个长度 \(2\) 的幂的序列是为了方便计算,也好写

Code:

/*Copyright (C) 2013-2022 LZE*/
#include<bits/stdc++.h>
#define INF 0x7fffffff
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N = 1000010;
ll T,n,m;
ll a[N] = {0},b[N] = {0};
int main(){
    scanf("%lld",&n);
    for(ll i = 1;i <= n;i++)scanf("%lld",&a[i]);
    ll p,lp,rp,limit = 1;
    for(ll i = 1;limit < n;i++)limit = limit * 2;
    ll bot = limit - n + 1;
    for(ll i = n + 1;i <= limit;i++)a[i] = -INF;
    for(ll step = 1;step <= limit;step = step * 2){
        for(ll i = 1;i <= limit;i = i + step){
            p = 1,lp = i,rp = i + step / 2;
            for(ll j = 1;j <= step;j++,p++){
                if(lp == i + step / 2){ b[p] = a[rp]; rp++; }
                else if(rp == i + step){ b[p] = a[lp]; lp++; }
                else if(a[lp] <= a[rp]){ b[p] = a[lp]; lp++; }
                else if(a[lp] > a[rp]){ b[p] = a[rp]; rp++; }
            }
            for(ll j = i,k = 1;k < p;j++,k++)a[j] = b[k];
        }
    }
    for(ll i = bot;i < n + bot;i++)printf("%lld ",a[i]);
    printf("\n");
    return 0;
}

posted @ 2021-10-20 20:40  lzexmpoane  阅读(71)  评论(0)    收藏  举报