思路:
首先想一下什么情况下会无解,因为一共有奇数个数字,而且可交换的前缀串长度也是奇数,所以无论如何变换,起初的数字所在位置的奇偶性一定都不会变,然后讨论如何构造,我们只需要以下5步便可以确定最后2个数字,依次搞定所有数字即可
代码:
#include <bits/stdc++.h>
#define all(x) (x).begin(), (x).end()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define make_unique(x) sort((x).begin(), (x).end()); (x).erase(unique((x).begin(), (x).end()), (x).end())
#define OP freopen("D:\\Users\\HP ZBook15\\CLionProjects\\untitled\\demo\\in.TXT","r",stdin);
#define CL freopen("D:\\Users\\HP ZBook15\\CLionProjects\\untitled\\demo\\out.TXT","w",stdout);
using namespace std;
inline int nxt() {
int x;
cin >> x;
return x;
}
void solve() {
int n = nxt();
vector<int> a(n);
for (int i = 0; i < n; ++i) {
a[i] = nxt() - 1;
}
for (int i = 0; i < n; ++i) {
if (a[i] % 2 != i % 2) {
cout << "-1\n";
return;
}
}
vector<int> ans;
//自定义一个变换turn
auto turn = [&](int l) {
if (l == 1) {
return;
}
//这五步变换的下标恰都是奇数,可以检查一下
assert(l % 2);
ans.push_back(l);
reverse(a.begin(), a.begin() + l);
};
while (n > 1) {
turn(find(all(a), n - 1) - a.begin() + 1);
turn(find(all(a), n - 2) - a.begin());
turn(find(all(a), n - 2) - a.begin() + 2);
turn(3);
turn(n);
n -= 2;
}
//检查是否排好序了
assert(is_sorted(all(a)));
cout << ans.size() << "\n";
for (int x : ans) {
cout << x << " ";
}
cout << "\n";
}
int main() {
closeSync
// OP
// CL
int t = nxt();
while (t--) {
solve();
}
return 0;
}
解释一下assert
语句:
这是用来提高代码可测试性的,可以对某种假设条件进行检查,在 C 语言中,断言被定义为宏的形式(assert(expression)),而不是函数,如果表达式 expression 的值为假(即为 0),那么它将首先向标准错误流 stderr 打印一条出错信息,然后再通过调用 abort 函数终止程序运行;否则,assert 无任何作用