题目大意:有 n 个数 1~n ,你可以选择一个区间使其变化任意位置,但是在这个区间内所有数必须换位置,现要求所有数回到自己位置问最少几次操作数
解法: 分类处理 – 分成下标与值相等 & 下标与值不相等两种
通过观察易得如果我们选定整个数组作为区间,只需让区间中值与下标不匹配的数重新匹配,若区间中还存在值与下标匹配的数,则先打乱他们,然后再第二部重新让他们匹配。
注意:我们判断的匹配的数应该在不匹配串的中间,如果在不匹配的串外围则没有必要选,因为我们选定的区间可以缩小
AC代码
#include <bits/stdc++.h>
using namespace std;
#define IO std::ios::sync_with_stdio(false); cin.tie(0)
#define ll long long
#define ull unsigned long long
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define per(i, l, r) for (int i = l; i >= r; --i)
#define mset(s, _) memset(s, _, sizeof(s))
#define mcpy(s, _) memcpy(s, _, sizeof(s))
#define pb push_back
#define pii pair <int, int>
#define vi vector<int>
#define vpii vector<pii>
#define mp(a, b) make_pair(a, b)
#define debug system("pause")
#define pll pair <ll, ll>
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define pline cout << endl << endl
inline int lowbit(int x) {return x & -x;}
template< typename T > inline void get_min(T &x, T y) {if(y < x) x = y;}
template< typename T > inline void get_max(T &x, T y) {if(x < y) x = y;}
inline int read() {
int x = 0, f = 0; char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
return f ? -x : x;
}
template<typename T> inline void print(T x) {
if (x < 0) putchar('-'), x = -x;
if (x >= 10) print(x / 10);
putchar(x % 10 + '0');
}
template<typename T> inline void print(T x, char let) {
print(x), putchar(let);
}
const int N = 2e5 + 10, mod = 100019;
int t, n, m;
int a[N];
int main() {
cin >> t;
while(t -- ) {
cin >> n; rep(i, 1, n) cin >> a[i];
int st = -1, ed = -1;
rep(i, 1, n) {
if(a[i] != i) {
st = i; break;
}
}
per(i, n, 1) {
if(a[i] != i) {
ed = i; break;
}
}
if(st == -1 && ed == -1) {
puts("0"); continue;
}
bool fini = 1, fg = 0;
rep(i, st, ed) {
if(a[i] == i) {
fg = 1; break;
}
}
if(fg) puts("2");
else puts("1");
}
return 0;
}