C 排序 解题报告

Posted ppprseter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C 排序 解题报告相关的知识,希望对你有一定的参考价值。

C 排序

题意

给一个(1sim n(nle 10^6))排列,求这个排列用冒泡排序从小到大排序的第(cnt)步的状态。这里步的定义为,比较一次算一步。


贴个我看的不是很懂的题解,嗯不是很懂里面01到底咋玩了,如果有理解的比较清楚的教教我这个菜鸡吧。
技术分享图片

说一下我自己的想法吧。

还是一轮一轮来,把(p_i=i)放好一次算一轮,先把整轮的给移动好

每一次把(a_j=i)放到(i)这个位置后,实际上是把(a_i)这个元素放到了右边第一个比(a_i)小的元素(a_k)的位置,然后(a_k)右边第一个比它小的...一直到(a_j),转了一个圈圈。

然后我们考虑对这个操作做一个延迟,比如当前我们处理到(i)了。

如果(i)这个地方还需要被放好成(p_i=i),那么原来位置(p)的东西就被顶出去了,它肯定是被顶到第一个比Ta小的地方了,当然Ta在之后也可能被顶,然后我们先把这个值给放到存着准备去顶别人。

然后如果这个地方没啥要求,就看这块地有没有人要了,容易发现越大的值越能顶别人,那么加上原来这个位置上的值中取一个最大的占领这个地方。

可以很简单的拿一个堆维护。

不过因为是排列,所以有个更加优秀的(O(n))做法

考虑到大的东西牛逼,别人顶不动,先把前面的(a_i=i)安排好,然后开始安排大的。

如果当前的位置不可用,肯定是安排好了或者被前面的大的顶了,那么就直接往后找一个没被顶的位置,把东西顶走就行了。


Code:

#include <cstdio>
#include <algorithm>
#define ll long long
const int N=1e6+10;
int pos[N],a[N],b[N],is[N];
int main()
{
    int n;ll cnt;scanf("%d%lld",&n,&cnt);
    for(int i=1;i<=n;i++) scanf("%d",a+i),pos[a[i]]=i;
    int k=0;
    while(cnt>=n-k-1) cnt=cnt-(n-++k);
    for(int i=1;i<=k;i++) is[i]=1,b[i]=i;
    int p=k+1;
    for(int i=n;i>k;i--)
    {
        int q=pos[i];
        if(is[q])
        {
            while(is[p]) ++p;
            q=p;
        }
        is[q]=1;
        b[q]=i;
    }
    for(int i=k+2;i<=n&&cnt;i++,--cnt) if(b[k+1]>b[i]) std::swap(b[k+1],b[i]);
    for(int i=1;i<=n;i++) printf("%d ",b[i]);
    return 0;
}

2019.1.9

以上是关于C 排序 解题报告的主要内容,如果未能解决你的问题,请参考以下文章

字符串排序解题报告

模拟题(63550802...)解题报告贪心拓扑排序找规律树相关

2020.4.19 个人rating赛 解题+补题报告

[解题报告] CSDN竞赛第18期

[解题报告] CSDN竞赛第18期

解题报告力扣 第 279 场周赛