『8.20 模拟赛』冒泡排序
Posted fang-hao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了『8.20 模拟赛』冒泡排序相关的知识,希望对你有一定的参考价值。
题目描述
给定n,k,和一个长度为n的序列,请输出这个序列冒泡排序k次之后的结果。
解题思路
我们观察上面给出的伪代码,可以发现这是一段把代码排序成升序的代码,那我们来考虑一下冒牌排序的几个特征。
一个大的数要向右交换,但是一次交换之后就可以换很多位置,所以换一次就不知道跑到哪里去了,所以很难维护。
一个小的数每次最多和它左边的更大的数交换一次,所以一次最多向左边跑一个位置,比大数不知道好维护到那里去了。
进一步思考,k次交换之后,最多可以向左跑k步,也就是说k+1位置的数最远能跑到1的位置上来,那我们就可以大胆的猜想了,前k+1个数在第一轮交换之后最小的数会到第一个位置。假如前k+1个中最小的数没能跑到第一个位置,那说明一定有一个比它小的数会在它的左边挡它,和我们的假设矛盾,所以猜想成立。
以此类推,第k+2个数最多到第二个位置上,按照我们的结论,第二个位置上的数应该是1 ~ k+2之间除去第一个位置的数以外的最小的数。
接着推下去,我们就完成了所有的数的位置的计算。
可以看出来,我们需要维护一个最小值,显然可以使用线段树,也可以使用优先队列,注意push的时候要用负值。
代码
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int maxn=100050; 8 int n,k; 9 int a[maxn]; 10 priority_queue<int>q; 11 int main(){ 12 scanf("%d%d",&n,&k); 13 for(register int i=1;i<=n;i++)scanf("%d",&a[i]); 14 for(register int i=1;i<=min(n,k+1);i++){ 15 q.push(-a[i]); 16 } 17 for(register int i=2;i+k<=n;i++){ 18 printf("%d ",-q.top()); 19 q.pop(); 20 q.push(-a[i+k]); 21 } 22 while(!q.empty()){ 23 printf("%d ",-q.top()); 24 q.pop(); 25 } 26 }
以上是关于『8.20 模拟赛』冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章