1 条题解
-
0
题目题解
问题理解
给定数组 和整数 。每次操作可以选择长度 的子数组,删除其中第 小的元素(若有多个相同值则任选一个)。问能否通过若干次操作使剩余数组成为回文。
第一步:哪些元素可以删除?
关键观察:
只要数组中仍然保留着最小的 个元素(按值排序),就可以任意删除其他元素。证明:
设 为第 小的元素值(若 则无限制)。
对于任何值 的元素,它一定是某个子数组的第 小(因为至少有 个更小的元素在数组中)。
我们可以通过收缩子数组边界,使该元素恰好成为第 小,从而删除它。
因此,所有大于 的元素都可以被删除。而对于值等于 的元素,它们可能成为第 小,也可能不成为,取决于是否有足够多的更小元素。
但无论如何,值小于 的元素永远不能被删除,因为它们是前 小,在任何长度 的子数组中,它们至少是第 小,永远不会成为第 小。
第二步:简化问题
设 为第 小的值(若 则 可视为 或不存在)。
根据上述结论:- 所有值 的元素必须保留(不能删)。
- 所有值 的元素都可以删除(且应该删除,因为它们会干扰回文)。
- 值 的元素可以删也可以留,但删除它们会消耗“配额”。
因此,我们可以先删除所有 的元素,得到新数组 ,只包含 的元素。
设 ,其中值 的有 个,值 的有 个。
由于 是第 小,我们有 。
所以 ,其中 是原数组中值为 的个数。
第三步:构造回文
现在数组 由 个小于 的值和若干等于 的值组成。
我们希望删除一些等于 的元素(因为小于 的不能删),使得剩余数组成为回文。设我们保留的等于 的个数为 ,则总保留元素数为 。
我们可以在 上使用双指针从两端向中间匹配:- 若 ,则保留这两个元素,指针移动。
- 若 ,则必须删除其中一个等于 的元素(因为小于 的不能删,且它们互不相同),并消耗一次“删除配额”。如果两个都不等于 ,则无法匹配,输出
"NO"。
初始可删除的 的个数为 (即所有等于 的元素)。
每删除一个 ,配额减少 。
若过程中配额不足或无法匹配,则"NO";否则"YES"。
第四步:边界情况
-
当 时,没有必须保留的元素,可以删除任意元素。此时总是可以构造回文(例如只保留一个元素,或删除到空数组),所以直接输出
"YES"。 -
当 时,按照上述双指针过程判断。
第五步:算法步骤
- 若 ,输出
"YES"。 - 否则:
- 对 排序,找到第 小的值 。
- 构造新数组 ,只包含 的元素。
- 设 (值为 的元素个数,即可以删除的 的数量)。
- 双指针 ,遍历:
- 若 ,, 。
- 否则:
- 若 ,失败。
- 若 ,则删除它:, 。
- 否则若 ,则删除它:, 。
- 否则失败。
- 若遍历完成,输出
"YES",否则"NO"。
时间复杂度
- 排序:。
- 双指针:。
- 总复杂度 ,满足 。
代码实现
#include <bits/stdc++.h> using namespace std; void solve() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; i++) { cin >> a[i]; } if (k == 1) { cout << "YES\n"; return; } // 找第 k-1 小的值 vector<int> b = a; sort(b.begin(), b.end()); int x = b[k - 2]; // 第 k-1 小的值(0-indexed) // 构造只包含 <= x 的数组 vector<int> c; int cnt_x = 0; for (int v : a) { if (v <= x) { c.push_back(v); if (v == x) cnt_x++; } } int spare = cnt_x; // 可以删除的 x 的个数 int L = 0, R = c.size() - 1; bool ok = true; while (L < R) { if (c[L] == c[R]) { L++; R--; } else { if (spare == 0) { ok = false; break; } if (c[L] == x) { L++; spare--; } else if (c[R] == x) { R--; spare--; } else { ok = false; break; } } } cout << (ok ? "YES" : "NO") << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) { solve(); } return 0; }
验证样例
输入:
8 5 3 5 4 3 4 5 4 1 1 1 2 1 6 6 2 3 4 5 3 2 5 4 5 2 4 3 1 8 5 4 7 1 2 3 1 3 4 5 4 1 2 1 2 2 3 3 1 2 2 4 4 2 1 2 2输出:
YES YES YES NO NO YES NO YES与题目输出一致。
总结
本题的关键在于:
- 识别出只有最小的 个元素不可删除。
- 将问题简化为只保留 的元素,并利用双指针匹配回文,必要时删除值为 的元素。
- 1
信息
- ID
- 6254
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者