给定一个数列 a,这个数列满足ai != aj(i != j),现在要求你把这个数列从小到大排序,每次允许你交换其中任意一对数,请问最少需要几次交换?
输入
第一行是一个整数,代表数字个数n(1 ≤ n ≤ 1e5).
第二行有n个整数用空格分隔开,表示数列a(?2e31< ai <2e31?1).
输出
只有一行,包含一个数,表示最少的交换次数。
Input
8
8 23 4 16 77 -5 53 100
Output
5
解析:
快排后的位置应该是每个数的最终位置,也就是说如果一个数移动到相应的位置后,就不用动了,这样的交换应该就是交换次数最少的。
如样例产生的效果:
8 23 4 16 77 -5 53 100
-5 23 4 16 77 8 53 100
-5 4 23 16 77 8 53 100
-5 4 8 16 77 23 53 100
-5 4 8 16 77 23 53 100
-5 4 8 16 23 77 53 100
-5 4 8 16 23 53 77 100
-5 4 8 16 23 53 77 100
-5 4 8 16 23 53 77 100
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int gcd(int a,int b) { return b? gcd(b,a%b) : a; }
typedef pair<int,int> PII;
const double PI=acos(-1.0);
const int N=2e6+10;
struct node
{
int x,id;
}str[N];
bool cmp(node a,node b)
{
return a.x<b.x;
}
int a[N];
int n;
void solve()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i];
str[i]={a[i],i};
}
sort (str+1,str+n+1,cmp);
int ans=0;
for (int i=1;i<=n;i++)
{
if (a[i]!=str[i].x)
{
ans++;
int t=a[i];
swap(a[i],a[str[i].id]); //交换两个数的位置
int l=i+1,r=n;
while (l<r)
{
int mid=l+r>>1;
if (str[mid].x>=t) r=mid;
else l=mid+1;
}
str[l].id=str[i].id; //相应的更新数a[i]的位置,由原来的str[l].id变成了str[i].id
}
}
cout<<ans;
}
signed main()
{
ios;
int T=1;
//cin>>T;
while (T--) solve();
return 0;
}