题解:CF1973E Cat, Fox and Swaps
思路参考官方题解,但其中对官方题解的思路和略过的部分进行了详细补充,证明了所有题解草草略过的部分,希望读者能认真阅读超链接部分的文字。
开始前,先判断排列是否已经有序,若有序,答案为
首先考虑
- 不存在
c = 0 的情况,否则排列有序。 -
-
观察到若要交换
设
注意到
事实上这是充分的。
先把不等式摆上来:
注意现在统计的数对是
引理:对于任意的
这样,
- 交换
X, x - X - 交换
x - X, X + 1 ,这一步的合法性证明 - 交换
X, x - X
这样,
最后统计答案,答案是
从
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
#ifdef ONLINE_JUDGE
#define debug(...) 0
#else
#define debug(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#endif
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int tt;
cin >> tt;
while (tt--) {
int n;
cin >> n;
vector<int> p(n);
set<int> st;
int cnt = 0;
for (int i = 0; i < n; i++) {
cin >> p[i];
if (i + 1 != p[i])
st.insert(p[i] + i + 1);
}
if (is_sorted(p.begin(), p.end())) {
cout << 2ll * n * (2 * n + 1) / 2 << "\n";
continue;
}
ll ans = st.size() == 1;
int L = n, R = 1;
for (int i = 0; i < n; i++) {
if (p[i] != i + 1) {
L = min(L, i + 1);
R = max(R, i + 1);
}
}
for (int i = R + 1; i <= 2 * n; i++)
ans += min(L + n, i - 1);
cout << ans << "\n";
}
return 0;
}
闲话