知识点哈希

校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。
描述
对于给定的由 nn 个整数组成的数组 {a1,a2,...,an}{a1,a2,...,an} ,你需要按照下述规则进行操作:
1. 1.从数组中选出连续的 mm 个元素(即选择一个长度为 mm 的连续子数组);
2. 2.将数组中剩余的 n−mn−m 个元素重新排序;
3. 3.在重新排序后的数组中选择一个位置,顺序插入刚刚选出的 mm 个元素;
问是否存在至少一种方案,使得最终得到的数组是个严格递增或严格递减数组。
输入描述:
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≦T≦2×105)T(1≦T≦2×105) 代表数据组数,每组测试数据描述如下:
第一行输入两个整数 n,m(1≦n≦2×105; 1≦m≦n)n,m(1≦n≦2×105; 1≦m≦n) 代表数组长度、你需要取出的元素数量。
第二行输入 nn 个整数 a1,a2,...,an(1≦ai≦109)a1,a2,...,an(1≦ai≦109) 代表数组元素。
除此之外,保证单个测试文件的 nn 之和不超过 2×1052×105 。
输出描述:
对于每一组测试数据,如果存在至少一种方案,使得最终得到的数组是个严格递增或严格递减数组,在单独的一行上输出 YESYES ;否则,直接输出 NONO 。
示例1
输入:
4
5 5
1 2 3 4 5
3 2
9 2 4
6 3
12 3 8 7 6 5
5 3
1 3 2 4 5
复制输出:
YES
YES
YES
NO
复制说明:
对于第一组测试数据,不需要进行任何操作,数组已经是严格递增数组。
对于第二组测试数据,选择区间 [2,3][2,3] ,随后将这两个元素插入到 99 之前,得到 {2,4,9}{2,4,9} 。
对于第三组测试数据,符合要求的方案为,选择区间 [3,5][3,5] ,随后将剩余的元素重新排列得到 {12,5,3}{12,5,3} ,随后将这三个元素插入到 1212 之后,得到 {12,8,7,6,5,3}{12,8,7,6,5,3} 。
cpp
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int a[N], b[N];
int n, m;
int getPos(int x, int opt) {
int l = 1, r = n;
int pos = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (opt == 1) {
// b递增
if (b[mid] <= x) {
l = mid + 1;
pos = mid;
} else r = mid - 1;
} else {
// b递减
if (b[mid] >= x) {
l = mid + 1;
pos = mid;
} else r = mid - 1;
}
}
return pos;
}
void solve() {
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
b[i] = a[i];
}
sort(b + 1, b + 1 + n);
for (int i = 1; i <= n; i ++ ) {
if (b[i] == b[i - 1]) {
cout << "NO\n";
return ;
}
}
for (int i = 1; i + m - 1 <= n; i ++ ) {
int j = i + 1;
while (j <= n && getPos(a[j], 1) - 1 == getPos(a[j - 1], 1)) j ++;
if (j - i >= m) {
cout << "YES\n";
return ;
}
i = j - 1;
}
reverse(b + 1, b + 1 + n);
for (int i = 1; i + m - 1 <= n; i ++ ) {
int j = i + 1;
while (j <= n && getPos(a[j], 2) - 1 == getPos(a[j - 1], 2)) j ++;
if (j - i >= m) {
cout << "YES\n";
return ;
}
i = j - 1;
}
cout << "NO\n";
}
int main(){
int T; cin >> T;
while (T -- ) solve();
return 0;
}