習題:Inversion SwapSort(思維)
阿新 • • 發佈:2020-07-20
題目
思路
比較巧妙的一道構造題
首先考慮排列的情況
因為是排列,所以每一個數位上的最終狀態一定是固定的
設\(b_i\)滿足\(a_{b_i}=i\)
如果交換\(a_{b_i},a_{b_j}\),那麼\(b_i,b_j\)一定也會被交換
再者,如果\(a\)有序,那麼\(b\)一定也有序,反之亦然
考慮逆序對對映到\(b\)上會是什麼情況
\(b_i<b_j,a_{b_i}>a_{b_j}\)
考慮到\(b\)陣列的定義
\(a_{b_i}>a_{b_j}\Rightarrow i>j\)
即對於\(b\)陣列,每一對滿足\(\begin{cases}b_i<b_j\\i>j\end{cases}\)
此處容易發現這就是逆序對的形式,同時,對於\(a\)的逆序對,\(b\)一定有一個唯一的與其對應
即我們將b進行一個氣泡排序即可
記錄下需要交換的\(b_i,b_{i+1}\)
那麼對於數列的情況也是一樣的,用兩個關鍵字來表示一個數即可
程式碼
#include<iostream> #include<algorithm> #include<map> #include<vector> using namespace std; #define x first #define y second int n; int b[1005]; pair<int,int> a[1005],c[1005]; map<int,int> tot; vector<pair<int,int> > ans; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>a[i].x; a[i].y=++tot[a[i].x]; c[i]=a[i]; } sort(c+1,c+n+1); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(c[i]==a[j]) { b[i]=j; break; } } } for(int i=n;i>=1;i--) { for(int j=1;j<i;j++) { if(b[j]>b[j+1]) { swap(b[j],b[j+1]); ans.push_back(make_pair(b[j],b[j+1])); } } } cout<<ans.size()<<endl; for(int i=0;i<ans.size();i++) cout<<ans[i].x<<' '<<ans[i].y<<endl; return 0; }