zl程序教程

您现在的位置是:首页 >  其他

当前栏目

1067 Sort with Swap(0, i) (25 分)【难度: 中 / 知识点: 置换群】

知识点 with 25 Sort swap 难度 1067
2023-09-11 14:15:52 时间

在这里插入图片描述
https://pintia.cn/problem-sets/994805342720868352/problems/994805403651522560
这种相关的题目见过很多次了。
常见的是只可以交换相邻两项求,有序后最少的步数。这类模型直接求逆序对即可。
还有一种模型是可以任意的交换两个数,求有序后最小的步数,答案是 n-环的个数。
本题和上面的差不多的思路,不过是加了必须通过0来交换的这一条限制。
首先,可以分析的得出,这个数组对应图的话都是一个个的环,向这种只有环的图称为置换图

  • 如果这个数本身是一个自环,那么说明他已经在对应的位置了,那么直接跳过。
  • 如果一个环和0在同一个环内,共有cnt个点,那么我们需要交换 cnt-1 此。
  • 如果一个环没有0,且共有cnt个点,那么首先我们得先将0加进来,然后再依次交换。加入进来1次操作,cnt+1个点交换 需要cnt次 故共cnt+1次
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],st[N],n,ans;
int main(void)
{
	cin>>n;
	for(int i=0;i<n;i++) cin>>a[i];
	for(int i=0;i<n;i++)
	{
		if(a[i]==i) continue;//自环
		if(!st[i]) 
		{
			bool flag=false;
			int cnt=0;//点的个数
			for(int j=i;!st[j];j=a[j])
			{
				if(j==0) flag=true;
				cnt++;
				st[j]=1;
			}
			if(flag) ans+=cnt-1;//和零在同一个环
			else ans+=cnt+1;//和零不在同一个环
		}
	}
	cout<<ans<<endl;
	return 0;
}