题目地址
https://codeforces.com/problemset/problem/1838/B
题目抽象
给一个长度为 n 的数组 a a a,它是 1 1 1 到 n n n 数字的排列组合,要求你找到两个下标 i i i 和 j j j,使得交换 a i a_i ai 和 a j a_j aj 后, a a a 的连续子序列所能形成的排列组合越少越好
数据范围:
3
≤
n
≤
2
⋅
1
0
5
3\le n \le 2\cdot 10^5
3≤n≤2⋅105
1
≤
a
i
≤
n
1\le a_i \le n
1≤ai≤n
题目类型
构造
解题思路
首先,不管怎么交换,
[
1
]
,
[
1
…
n
]
[1], [1 \dots n]
[1],[1…n] 这两个排列组合一定会存在,只选1和全选
那么我们的目的就是让其他的组合尽可能不出现
我们来看最容易出现的排列组合是
[
1
,
2
]
[1,2]
[1,2],所以
1
1
1 和
2
2
2 只要不挨在一起,就不会出现
[
1
,
2
]
[1,2]
[1,2]
对于长度为
k
,
n
>
k
>
2
k, n > k > 2
k,n>k>2 的排列组合,它的子序列一定要包含
1
1
1 和
2
2
2,且
1
,
2
1,2
1,2 之间不能包含比
k
k
k 大的数字,所以如果我们将最大的
n
n
n 放在
1
,
2
1,2
1,2 之间,那么一定无法形成长度为
k
k
k 的排列组合
答案就很简单
找到
1
,
2
,
n
1,2,n
1,2,n 的位置,判断他们的位置,把
n
n
n 放到
1
1
1 和
2
2
2 之间
代码
#include <bits/stdc++.h>
using namespace std;
int n;
void solve() {
cin >> n;
int one, two, mx;
for (int i = 1, a; i <= n; i ++) {
cin >> a;
if (a == 1) one = i;
else if (a == 2) two = i;
else if (a == n) mx = i;
}
if (mx > one && mx > two) {
cout << mx << ' ' << max(one, two) << endl;
} else if (mx < one && mx < two) {
cout << mx << ' ' << min(one, two) << endl;
} else {
cout << "1 1" << endl;
}
}
int main() {
int T; cin >> T; while (T--) solve();
}