题面
A permutation of length is an array consisting of distinct integers from to in arbitrary order. For example, is a permutation, but and are not permutations.
You are given a permutation of length . You can perform the following operation exactly once:
- Choose two integers ().
- Reverse the segment in the permutation .
Your task is to output the lexicographically maximum permutation that can be obtained by performing this operation. A permutation is lexicographically greater than a permutation if for the first position where they differ, it holds that .
Input
Each test consists of several test cases. The first line contains a single integer () — the number of test cases. The description of the test cases follows.
The first line of each test case contains the number ().
The second line of each test case contains distinct integers .
It is guaranteed that the sum of the values of across all test cases does not exceed .
Output
For each test case, output the lexicographically maximum permutation that can be obtained with one operation.
思路
按照题意,我们需要确定一个区间 用于反转,并保证之后的串的字典序是最大的,也就是保证这个排列目前处于“完美状态”
NOTE这个“完美状态”如何理解?
给出例子:
遍历到第 位:对应值为 ,对于长度为 的排列来说,不可能有比 还大的值了,所以目前的排列处于完美状态
遍历到第 位:对应值为 ,对于长度为 的排列来说,第二位理论上的字典序最大值就是 也就是这里的 (这里用 指代排列长度)
遍历到第 位:对应值为 ,但是在一个这个排列中,有比这个值更大的数字存在,所以这个位置上的数字不是完美状态
以上,就是对一个排列的字典序的所谓“完美状态”的理解
本质上,就是看在给定的元素组成的所有有可能的排列中,字典序最大的那一个,对应位置的各个元素也就被称为所谓的“完美状态”
由上,不难看出,对于这个应该反转的起点 ,其实就是第一个破坏整个排列完美状态的位置
而对应的 ,就是本应该在 位置的数的位置,在上面的例子中,
NOTE推广例子:
很明显,按照上面的推理,位置 的 并不完美,所以
接下来,我们就要查找,在位置 上,到底应该适合什么数字?
计算,很明显,位置 上的数字应该是
推导
位置 上的数字应该是
位置 上的数字应该是
位置 上的数字应该是
位置 上的数字应该是
对于上述问题给出的例子来说,这里的 就是 ;而由上面的推导,不难看出, 就是满足 的位置
所以,对于刚刚的例子,这个应该反转的区间就是 ,反转之后得到的排列,正是字典序最大的()
因此在代码实现上,我们只需要对这个区间左端点 以前的排列正常输出,而在区间内的元素进行倒序输出即可
代码
#include <bits/stdc++.h>
using namespace std;
int main() { int t; cin >> t;
while(t --) { int n; cin >> n;
int p[n + 5], l = 1;
for(int i = 1; i <= n; i ++) { cin >> p[i]; }
while(l <= n && p[l] == n - l + 1) l ++; int r = -1;
for(int i = l; i <= n; i ++) { if(p[i] == n - l + 1) r = i; }
for(int i = 1; i < l; i ++ ) cout << p[i] << ' ';
if(r != -1) { for( int i = r; i >= l; i --) cout << p[i] << ' '; for( int i = r + 1; i <= n; i ++) cout << p[i] << ' '; } cout << '\n'; }}