CF1768D Lucky Permutation Solution
CF1768D 题意不再简述。
首先题目要求变成逆序对只有一个的排列,也就是说,我们可以先考虑将一个排列通过交换元素变成另一个排列最小的步数,我们可以将两个排列相同位置上的数连边,很显然会形成几个环,若排列长度为
然后,题目要求变成的目标排列是逆序对只有一个,也就是目标排列是将升序排列中一对相邻元素交换后得到的,显然就有一个
然而这并不能过此题,考虑优化,我们交换操作至多会影响两个环,也就是说,我们先对原序列和生序序列之间处理出环,然后考虑交换的位置,设交换的两个位置是
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 2e5 + 10;
int n, A[N], T[N], id[N], bel[N], fa[N], cnt[N];
int Find(int x) {
if (fa[x] == x) return x;
return fa[x] = Find(fa[x]);
}
int main() {
ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
int _; cin >> _;
while (_ --) {
cin >> n;
for (int i = 1; i <= n; i ++) {
cin >> A[i]; fa[i] = i; cnt[i] = 1;
}
for (int i = 1; i <= n; i ++) {
if (Find(A[i]) != Find(i)) {
cnt[Find(i)] += cnt[Find(A[i])]; cnt[Find(A[i])] = 0;
fa[Find(A[i])] = Find(i);
}
}
int S = 0, Ans = 1e9;
for (int i = 1; i <= n; i ++)
if (fa[i] == i) S += cnt[i] - 1;
for (int i = 1; i < n; i ++) {
if (Find(i) == Find(i + 1)) Ans = min(Ans, S - 1);
else Ans = min(Ans, S + 1);
}
cout << Ans << "\n";
}
return 0;
}
本文作者:LaDeX
本文链接:https://www.cnblogs.com/LaDeX-Blog/p/18331059/CF1768D-sol
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步