Codeforces Round #598 (Div. 3) B Minimize the Permutation

B. Minimize the Permutation

You are given a permutation of length nn. Recall that the permutation is an array consisting of nn distinct integers from 11 to nn in arbitrary order. For example, [2,3,1,5,4][2,3,1,5,4] is a permutation, but [1,2,2][1,2,2] is not a permutation (22 appears twice in the array) and [1,3,4][1,3,4] is also not a permutation (n=3n=3 but there is 44 in the array).

You can perform at most n1n−1 operations with the given permutation (it is possible that you don't perform any operations at all). The ii-th operation allows you to swap elements of the given permutation on positions ii and i+1i+1. Each operation can be performed at most once. The operations can be performed in arbitrary order.

Your task is to find the lexicographically minimum possible permutation obtained by performing some of the given operations in some order.

You can see the definition of the lexicographical order in the notes section.

You have to answer qq independent test cases.

For example, let's consider the permutation [5,4,1,3,2][5,4,1,3,2]. The minimum possible permutation we can obtain is [1,5,2,4,3][1,5,2,4,3] and we can do it in the following way:

  1. perform the second operation (swap the second and the third elements) and obtain the permutation [5,1,4,3,2][5,1,4,3,2];
  2. perform the fourth operation (swap the fourth and the fifth elements) and obtain the permutation [5,1,4,2,3][5,1,4,2,3];
  3. perform the third operation (swap the third and the fourth elements) and obtain the permutation [5,1,2,4,3][5,1,2,4,3].
  4. perform the first operation (swap the first and the second elements) and obtain the permutation [1,5,2,4,3][1,5,2,4,3];

Another example is [1,2,4,3][1,2,4,3]. The minimum possible permutation we can obtain is [1,2,3,4][1,2,3,4] by performing the third operation (swap the third and the fourth elements).

Input

The first line of the input contains one integer qq (1q1001≤q≤100) — the number of test cases. Then qq test cases follow.

The first line of the test case contains one integer nn (1n1001≤n≤100) — the number of elements in the permutation.

The second line of the test case contains nn distinct integers from 11 to nn — the given permutation.

Output

For each test case, print the answer on it — the lexicograhically minimum possible permutation obtained by performing some of the given operations in some order.

Example
input
Copy
4
5
5 4 1 3 2
4
1 2 4 3
1
1
4
4 3 2 1
output
Copy
1 5 2 4 3 
1 2 3 4 
1 
1 4 3 2 
Note

Recall that the permutation pp of length nn is lexicographically less than the permutation qq of length nn if there is such index ini≤n that for all jj from 11 to i1i−1 the condition pj=qjpj=qj is satisfied, and pi<qipi<qi. For example:

  • p=[1,3,5,2,4]p=[1,3,5,2,4] is less than q=[1,3,5,4,2]q=[1,3,5,4,2] (such i=4i=4 exists, that pi<qipi<qi and for each j<ij<i holds pj=qjpj=qj),
  • p=[1,2]p=[1,2] is less than q=[2,1]q=[2,1] (such i=1i=1 exists, that pi<qipi<qi and for each j<ij<i holds pj=qjpj=qj).

选择最小的往前走。

#include<bits/stdc++.h>
using namespace std;
vector<int>p;
int pos[105];
int vis[105];
void solve() {
    p.clear();
    int n;
    scanf("%d",&n);
    memset(vis,0,sizeof(vis));
    memset(pos,0,sizeof(pos));
    for(int i=0; i<n; i++) {
        int x;
        scanf("%d",&x);
        p.push_back(x);//存数字 
        pos[x]=i;//记录每个数字的下标 
    } 
    for(int i=1; i<=n; i++) {//移动最小的数字 
        int flag = 1;
        while(flag==1) {
            if(pos[i]>0&&vis[pos[i]-1]==0) {//如果pos[1]=0,说明已经在一号位,就不用移动,
            //如果没在一号位,他的前一位没有和他进行过交换 
                vis[pos[i]-1]=1;//那么就标记,交换过 
                int now=pos[i],pnow=pos[i]-1; 
                swap(p[now],p[pnow]);//交换数字 
                swap(pos[p[now]],pos[p[pnow]]);//交换下标 
            } else {
                flag=0;
            }
        }
        vis[pos[i]]=1;//当目前最小的数字已经不能再交换了,那么他的位置也就不能再动,就标记 
    }
    for(int i=0; i<p.size(); i++) {  //最后输出 
        cout<<p[i]<<" ";
    }
    cout<<endl;

}
int main() {
    int t;
    scanf("%d",&t);
    while(t--)solve();
}
//从后往前扫,遇到能往左边挪的就往左边挪。
//当然还有位置没有挪过,那就把没有被挪过的地方记录下来,然后再贪心把小的往左边挪。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
int a[maxn];
int vis[maxn];
int n;
int main() {
    int T;
    cin >> T;
    while(T--) {
        cin >> n;
        for(int i = 1; i <= n; i++) {
            cin >> a[i];
            vis[i] = 0;
        }
        for(int i = n - 1; i >= 1; i--) {
            if(a[i] > a[i+1]) {
                swap(a[i], a[i+1]);
                vis[i] = 1;
            }
        }
        for(int i = 1; i <= n - 1; i++) {
            if(vis[i] == 0) {
                if(a[i] > a[i+1])
                    swap(a[i], a[i+1]);
            }
        }
        for(int i = 1; i <= n; i++)
            printf("%d ", a[i]);
        puts("");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/11800131.html