1553. 用 Swap(0, i) 操作进行排序
原题传送:AcWing 1553. 用 Swap(0, i) 操作进行排序
给定一个 0 ∼ N − 1 0 \sim N-1 0∼N−1 的随机排列,将其变为升序排列非常简单。
如果只能使用Swap(0, *)
操作(将数字
0
0
0 和另一个数字交换位置),使得序列变成升序排列呢?
例如,给定序列{4, 0, 2, 1, 3}
,我们可以通过下列交换操作,得到升序序列:
Swap(0, 1) => {4, 1, 2, 0, 3}
Swap(0, 3) => {4, 1, 2, 3, 0}
Swap(0, 4) => {0, 1, 2, 3, 4}
现在,请你求出将给定序列按如上交换操作变为升序序列,至少需要多少步操作。
输入格式
第一行包含整数 N N N ,表示序列中元素个数。
第二行包含一个 0 ∼ N − 1 0 \sim N-1 0∼N−1 的随机排列序列。
输出格式
输出所需最少操作步数。
数据范围
1 ≤ N ≤ 1 0 5 1 \le N \le 10^5 1≤N≤105
输入样例:
10
3 5 7 2 6 4 9 0 8 1
输出样例:
9
思路:
通过将当前的数指向对应下标,可以将本问题转换成图论的问题,即将所有环处理成自环。先将与0在同一个环内的数处理成自环,然后将其他非自环的环处理成自环。
题解:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
int p[N];
int main()
{
cin >> n;
for(int i = 0; i < n; i++)
{
int id;
cin >> id;
p[id] = i;
}
int res = 0;
for(int i = 1; i < n; i++)
{
while(p[0])
swap(p[0], p[p[0]]), res++;
while(i < n && p[i] == i)
i++;
if(i < n)
swap(p[0], p[i]), res++;
}
cout << res << endl;
return 0;
}