其他分享
首页 > 其他分享> > 排序

排序

作者:互联网

排序

zzq近日发明了一种最新的排序算法 FastSort\text{FastSort}FastSort,它的伪代码大致如下:

当然,这个伪代码里的 cntcntcnt 对排序来说没什么用,它只是用来指示这个算法的运行效果的。

zzq很喜欢这个算法,于是他打算用它来给一个 1,2…n1,2 \ldots n1,2…n 的排列 aaa 排序。为了清楚地获取算法的运行过程,zzq决定在每次 cntcntcnt 改变时记录下当前的 cntcntcnt 和 aaa 便于分析。

zzq运行了这个算法之后就睡觉去了。第二天早上,zzq发现昨天停电了,日志里只剩下了记录下的最后一个 cnt 和 a。zzq不想再运行一遍算法了,于是他想让你确认一下记录是否正确。

一句话题意:对给定的 1,2…n1,2 \ldots n1,2…n 的排列 aaa 执行算法 FastSort,问当 cnt 刚刚变成输入中给定的值时的 a 序列。

输入格式

第一行两个整数,nnn 和 cntcntcnt。

第二行 nnn 个整数,表示 a1,a2…ana_1,a_2 \ldots a_na​1​​,a​2​​…a​n​​。保证是一个 1,2…n1,2 \ldots n1,2…n 的排列。

输出格式

一行 nnn 个整数,表示 cntcntcnt 恰好变成给定值时的 aaa 序列。

样例

样例输入1

5 3
4 3 2 5 1

样例输出1

2 4 3 5 1

样例输入2

9 16
1 9 8 2 3 7 5 4 6

样例输出2

1 2 8 9 3 7 5 4 6

数据范围与提示

对于所有数据,2≤n≤106,1≤cnt≤n(n−1)22 \leq n \leq 10^6,1 \leq cnt \leq \frac{n(n-1)}{2}2≤n≤10​6​​,1≤cnt≤​2​​n(n−1)​​。\par

Subtask 1(10pts):cnt≤107cnt \leq 10^7cnt≤10​7​​。

Subtask 2(10pts):ai=n+1−ia_i=n+1-ia​i​​=n+1−i。

Subtask 3(20pts):数据生成方式为,先选定 n≤100000n \leq 100000n≤100000 和 cntcntcnt,并初始化 ai=ia_i=ia​i​​=i(∀i∈[1,n]\forall i \in [1,n]∀i∈[1,n]),然后重复 101010 次,每次在 [1,n][1,n][1,n] 中独立均匀随机两个不同的整数 iii 和 jjj,并交换 aia_ia​i​​ 和 aja_ja​j​​。

Subtask 4(20pts):n≤50000n \leq 50000n≤50000。

Subtask 5(20pts):n≤200000n \leq 200000n≤200000。

Subtask 6(20pts):无特殊限制。

 


  solution 可以发现它其实是每次贪心的下降,然后循环移位。 那么我们考虑现在完成了k个整轮的排序。 剩下的不足一轮,暴力即可。 那么我们只需要知道这i轮之后的a数组长啥样。   我们考虑每一个位置i。记该位置初始权值ai。 统计1~i-1 的所有aj ,设第k大的为x。 如果x<a[i]说明i位置不会被换。因为k轮的终点都在i之前。 否则换到a[i]的就是x。 证明:假设比ai小的aj有num个。 那么前num轮就是每次删掉最小的aj。 后k-num轮,ai也参与了循环移位。 每次把第一个比ai大的移到ai。 k轮后就是x。   现在求每一个位置之前的第k大是几。 用数据结构维护即可。   简单说下一个巧妙的堆写法。 维护一个大小为k的大根堆 首先按权值从小到大扫描,把前k个权值的位置加进堆里。 然后继续扫每一个权值x。 如果这个x的位置在比堆顶大,那么可以发现它的前面有k个比他小,不用换。 否则取出堆顶并将x的位置加入堆。此时堆顶的位置之前有k个位置,且一定是权值最小的k个位置。 也就是该x将会被换到堆顶的位置。  
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #define maxn 1000006
 9 using namespace std;
10 int n,a[maxn],p[maxn];
11 long long cnt;
12 priority_queue<int>q;
13 void work(int k){
14     for(int i=1;i<=n;i++)p[a[i]]=i;
15     for(int i=1;i<=k;i++){
16         q.push(p[i]);a[i]=i;
17     }
18     for(int i=k+1;i<=n;i++){
19         q.push(p[i]);
20         if(q.top()==p[i]){q.pop();continue;}
21         else {a[q.top()]=i;q.pop();}
22     }
23 }
24 int main(){
25     freopen("sort.in","r",stdin);
26     freopen("sort.out","w",stdout);
27     cin>>n>>cnt;
28     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
29     for(int i=1;i<=n;i++){
30         if(cnt>=n-i)cnt-=n-i;
31         else {
32             if(i>1)work(i-1);
33             for(int j=i+1;j<=n&&cnt;j++,cnt--){
34                 if(a[i]>a[j])swap(a[i],a[j]);
35             }
36             break;
37         }
38     }
39     for(int i=1;i<=n;i++)printf("%d%c",a[i],i==n?'\n':' ');
40     return 0;
41 }
View Code

 

 

标签:cnt,include,cntcntcnt,zzq,leq,Subtask,排序
来源: https://www.cnblogs.com/liankewei/p/10389887.html