標籤:img std gis 之間 cstring 長度 http stream 很多
題目描述
給定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\n",-q.top());19 q.pop();20 q.push(-a[i+k]);21 }22 while(!q.empty()){23 printf("%d\n",-q.top());24 q.pop();25 }26 }
『8.20 類比賽』冒泡排序