3 2^k-分位数组

作者: 赵晓鹏时间限制: 1S章节: 递归与分治

 

 

#include <iostream>
#include <algorithm>
#include <queue>
#include <tuple>
#include <stack>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
const int LENGTH=(1<<22)+3;
int A[LENGTH]={1,1};
int pos=0;
const int groupLen=25;
const int h=160;
int recordPass=0;

inline int Partition(int left, int right, int x)
{
    A[pos]=A[left];
    int i = left, j = right+1;
    while(true)
    {
        while(i < j && A[--j] >= x);
        while(i < j && A[++i] < x);
        if(i>=j) break;
        swap(A[i], A[j]);
    }
    A[left]=A[i];
    A[i]=x;
    return i;
}
int select(int first, int last, int r)
{
    if(last - first < h)
    {
        priority_queue<int>Q(A + first, A + last + 1);
        for(int i=last; i>=first; --i)
        {
            A[i]=Q.top();
            Q.pop();
        }
        return A[r + first - 1];
    }
    pos=first+rand()%(last-first);
    int x = A[pos];
    int mid= Partition(first, last, x);
    int res = mid - first + 1;
    int locLeft=mid;
    int locRight=last+1;
    int m=0;
    if(r < res) return select(first, mid, r);
    else
    {
        while(true)
        {
            while(A[++locLeft]==x&&locLeft<locRight);
            while((A[--locRight]^x)&&locLeft<locRight);
            if(locLeft>=locRight)
            {
                m=locLeft-mid-1;
                break;
            }
            A[locRight]=A[locLeft];
            A[locLeft]=x;
        }
        if(m>=1&&r>=res&&r<=m+res-1) return x;
        else return select(mid + 1+m, last, r - res-m);
    }

}
void res(int left, int right, int leftNum, int rightNum, int k) {
    int B[rightNum+1];
    stack<tuple<int, int, int, int>> stk;
    stk.push(make_tuple(left, right, leftNum, rightNum));
    while (!stk.empty()) {
        int left, right, leftNum, rightNum;
        tie(left, right, leftNum, rightNum) = stk.top();
        stk.pop();
        if (leftNum > rightNum) {
            continue;
        }
        int mid = (leftNum + rightNum) >> 1;
        int midPos = (mid + 1) <<k;
        select(left, right, midPos - left + 1);
        B[mid]=A[midPos-1];
        stk.push(make_tuple(midPos + 1, right, mid + 1, rightNum));
        stk.push(make_tuple(left, midPos, leftNum, mid - 1));

    }
    for(int i=leftNum;i<=rightNum;++i){
        if(i==rightNum){
            printf("%d",B[i]);
        }
        else{
            printf("%d ",B[i]);
        }
    }
}
int main()
{
    int n,k,m;
    scanf("%d%d%d", &n,&k,&m);
    int  len=1<<n;
    for(int  i=2; i<len; ++i)
    {
        A[i]=(A[i-1]+A[i-2])%m;
    }
    int unit=1<<k;
    int maxNum=len/unit;
    res(0, len-1, 0,maxNum-1, k);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨骅麟(Hadrain Young)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值