zzq's sort [思维题]

sortsort


\color{red}{正解部分}

第一个 forfor 循环完成第 ii 次循环之后 ii 会到位置 ii,
所以可以考虑先处理出完成尽可能多的第一个 forfor 循环后的 {ai}\{a_i\}, 剩下的操作暴力处理,
现在的问题就是 (k,N](k, N] 的数字形式是什么,
设完成了 kk 次, 然后考虑 (k,N](k, N] 的数字怎么填,
首先设 aia_i 的位置为 pip_i, 现在处理 ai(k,N]a_i ∈ (k, N] 放哪些位置, 从大到小 处理,

  • pi>kp_i > k 时, 位置只可能往后移 .
  • pikp_i \le k 时, 其会被交换到 (k,N](k, N] 中第一个空位 .

由于是 从大到小 枚举, 所以 较大的数字 放置了之后, 不会被 较小的数字 交换到其它位置了, 相当于位置固定了 .


\color{red}{实现部分}

#include<bits/stdc++.h>
#define reg register

const int maxn = 1e6 + 5;

int N;
int A[maxn];
int p[maxn];
int vis[maxn];

long long cnt;

int main(){
        scanf("%d%lld", &N, &cnt);
        for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]), p[A[i]] = i;
        for(reg int i = 1; i <= N; i ++)
                if(cnt >= N-i) cnt -= N-i;
                else{
                        for(reg int j = 1; j < i; j ++) A[j] = j;
                        int t = i;
                        for(reg int j = N; j >= i; j --){
                                if(p[j] >= i && !vis[p[j]]) vis[p[j]] = 1;
                                else{ 
                                        while(vis[t] && t <= N) t ++;
                                        vis[t] = 1; A[t] = j;
                                }
                        }
                        t = 0;
                        for(reg int j = i+1; j <= N; j ++){
                                if(A[j] < A[i]) std::swap(A[i], A[j]);
                                if(++ t >= cnt) break ;
                        }
                        break ;
                }
        for(reg int i = 1; i <= N; i ++) printf("%d ", A[i]);
        return 0;
}
posted @ 2019-09-23 21:36  XXX_Zbr  阅读(131)  评论(0编辑  收藏  举报