题意:给你n个数字的序列,你可以一次操作一个区间(区间大小是偶数),交换区间的前半部分与后半部分,用不超过9^6的操作数使这个序列变成一个升序列。
思路:这个我一开始理解的是要用最少的操作数,然后就想了好久都没有想出来,但是发现了只需要从左到右进行操作就可以,每一数字最多只需要两次操作就可以了,但是一只输出的操作不是操作次数最少的(十分崩溃啊),然后后来发现不需要次数最少。。。。。。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <time.h>
#include <vector>
#define MAXN 100010
#define MAXE 210
#define INF 10000000
#define MOD 1000000007
#define LL long long
#define PI acos(-1.0)
using namespace std;
int arr[MAXN];
struct Node {
int left;
int right;
};
void SWAP(int left, int right) {
for (int i = left, j = left + (right - left + 1) / 2; j <= right; ++j, ++i)
swap(arr[i], arr[j]);
}
int main() {
std::ios::sync_with_stdio(false);
int T;
cin >> T;
for (int kase = 1; kase <= T; ++kase) {
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> arr[i];
}
vector<Node> vec;
Node t;
for (int i = 1; i <= n; ++i) {
if (arr[i] == i)
continue;
int pos = 0;
for (int j = i + 1; j <= n; ++j) {
if (arr[j] == i) {
pos = j;
break;
}
}
if (2 * pos - i - 1 > n) {
if ((pos - i) % 2) {
t.left = i;
t.right = pos;
vec.push_back(t);
SWAP(i, pos);
} else {
t.left = i + 1;
t.right = pos;
vec.push_back(t);
SWAP(i + 1, pos);
}
i--;
} else {
t.left = i;
t.right = 2 * pos - i - 1;
vec.push_back(t);
SWAP(i, 2 * pos - i - 1);
}
}
cout << vec.size() << endl;
for (int i = 0; i < vec.size(); ++i) {
cout << vec[i].left << " " << vec[i].right << endl;
}
}
return 0;
}
/*
2
6
5 4 6 3 2 1
5
1 2 3 4 5
*/