給定長度 n (1 ≤ n ≤ 1e5) 的排列 a[0..n-1](含 0 到 n-1 各一次)。固定點定義為 a[i] == i。允許最多交換一次任意兩個元素,求最大可能固定點數。
ans 直接統計。i != j 使 a[i]=j 且 a[j]=i,交換後兩者均成固定點。條件等價於 a[a[i]] == i 且 a[i] != i。ans 並標記固定點 is[i]=1。i,檢查 a[a[i]] == i,若真返回 ans+2。ans+1。ans。#include <cstdio>
#include <cstring>
using namespace std;
int fun(int a[], int is[], int n) {
int flag = 0;
for (int i = 0; i < n; i++) {
if (is[i] == 0) {
if (i == a[a[i]]) return 2;
flag++;
}
}
if (flag) return 1;
return 0;
}
int main() {
int n, a[100010], is[100010];
while (scanf("%d", &n) != EOF) {
int ans = 0;
memset(is, 0, sizeof(is));
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
if (a[i] == i) { is[i] = 1; ans++; }
}
printf("%d\n", ans + fun(a, is, n));
}
return 0;
}
時間 O(n),空間 O(n),滿足 n=1e5 限制。