題意:多組案例,先輸入資料的數目,在依次輸入資料,判斷將這些資料從小到大排列最少需要多少操作步數。(案例以輸入0結束)
案例:sample input59
1054
3123
0sample output60
分析:題目本質就是求逆序對了,簡單介紹一下。逆序對是指在序列 中,若aij),則(ai,aj)上一對逆序對。而逆序數顧名思義就是序列中逆序對的個數。例如: 1 2 3是順序,則逆序數是0;1 3 2中(2,3)滿足逆序對的條件,所以逆序數只有1; 3 2 1中(1,2)(1,3)(2,3)滿足逆序對,所以逆序是3。由定義不能想象,序列n的逆序數範圍在[0,n*(n-1)/2],其中順序時逆序數為 0,完全逆序時逆序數是n*(n-1)/2。
可以利用歸併排序時計算逆序個數,時間複雜度是nlog2n,而空間複雜度 2n。 利用歸併求逆序是指在對子序列s1和s2在歸併時,若s1[i]>s2[j](逆序狀況),則逆序數加上s1.length-i,因為s1 中i後面的數字對於s2[j]都是逆序的。具體看注釋吧。
歸併演算法基本思路
設兩個有序的子檔案放在同一向量中相鄰的位置上:r[low..m],r[m+1..high],先將它們合併到乙個區域性的暫存向量r1中,待合併完成後將r1複製回r[low..high]中。
合併過程中,設定i,j和p三個指標,其初值分別指向這三個記錄區的起始位置。合併時依次比較r[i]和r[j]的關鍵字,取關鍵字較小的記錄複製到r1[p]中,然後將被複製記錄的指標i或j加1,以及指向複製位置的指標p加1。
重複這一過程直至兩個輸入的子檔案有乙個已全部複製完畢(不妨稱其為空),此時將另一非空的子檔案中剩餘記錄依次複製到r1中即可。
源**:
1 #include 2#define max 500001
3int
a[max], b[max],i;
4long
long
ans;
5void merge(int l,int m,int r)//歸併6
15else
16 b[p++]=a[i++];17}
18while(i<=m) b[p++]=a[i++];//
非空輸入空間轉入輸出空間
19for(i=0;i//
歸併結束,結果複製到原輸入陣列
20 a[l+i]=b[i];21}
22void mergesort(int l2,int r2)//
歸併排序
2331}32
intmain( )
3343
return0;
44 }
超級快排 Ultra QuickSort
題目內容 在這個問題中,你需要分析特別的演算法。這個演算法通過對乙個包含n個元素的進行操作,一直交換相鄰的兩個序列的元素直到整個序列呈公升序排列。對於輸入序列9 1 0 5 4 ultra quicksort最終得到的輸出為0 1 4 5 9 你的任務就是來計算出ultra quicksort 至少...
Catalan數(卡特蘭數)
卡特蘭數 規定h 0 1,而h 1 1,h 2 2,h 3 5,h 4 14,h 5 42,h 6 132,h 7 429,h 8 1430,h 9 4862,h 10 16796,h 11 58786,h 12 208012,h 13 742900,h 14 2674440,h 15 969484...
卡特蘭數 Catalan數
卡特蘭數 規定h 0 1,而h 1 1,h 2 2,h 3 5,h 4 14,h 5 42,h 6 132,h 7 429,h 8 1430,h 9 4862,h 10 16796,h 11 58786,h 12 208012,h 13 742900,h 14 2674440,h 15 969484...