这道题的核心在于理解“交替共鸣序列”的定义,并找出删除哪一个元素后,剩下的序列能满足这个定义。
题目地址
解题思路
1.理解“交替共鸣序列”:
* 题目定义:序列中任意两个相邻元素的奇偶性都不同。
* 通俗理解:序列的奇偶性必须是交替出现的,例如 `奇, 偶, 奇, 偶` 或 `偶, 奇, 偶, 奇`。
* 特例:长度为 0 或 1 的序列天然满足条件。
2.分析删除操作:
* 我们需要尝试删除序列中的每一个元素,然后检查剩下的序列是否是“交替共鸣序列”。
* 直接模拟删除并检查的时间复杂度是 O(n²),对于 n ≤ 10⁶ 的数据规模会超时。我们需要一个 O(n) 的线性解法。
3.寻找高效方法:
* 一个序列如果不是“交替共鸣序列”,那一定是因为在某个位置 `i`,`a[i]` 和 `a[i+1]` 的奇偶性相同。我们称这个位置为“冲突点”。
* 当我们删除一个元素 `a[k]` 时,只会影响 `a[k-1]` 和 `a[k+1]` 之间的关系。序列中其他所有相邻元素的奇偶关系都保持不变。
* 因此,我们可以先遍历一遍原数组,找出所有“冲突点”的位置。
* 然后,对于每一个可能的删除位置 `k`,我们只需要检查:
* 删除 `a[k]` 是否会消除原有的冲突?
* 删除 `a[k]` 是否会引入新的冲突(即 `a[k-1]` 和 `a[k+1]` 的奇偶性是否相同)?
* 如果删除 `a[k]` 后,整个序列不再有任何冲突,那么 `k` 就是一个合法的删除位置。
4.算法步骤:
* **预处理**:遍历数组,用一个数组 `conflicts` 记录所有冲突点的位置。`conflicts[i]` 为 `true` 表示 `a[i]` 和 `a[i+1]` 奇偶性相同。
* **统计总冲突数**:计算 `conflicts` 数组中 `true` 的个数,记为 `total_conflicts`。
* **遍历删除位置**:对于每个位置 `k` (从 0 到 n-1):
* 计算删除 `a[k]` 会消除的冲突数 `removed_count`。这包括 `conflicts[k-1]` (如果 `k>0`) 和 `conflicts[k]` (如果 `k<n-1`)。
* 计算删除 `a[k]` 会引入的新冲突数 `added_count`。这只发生在 `k>0` 且 `k<n-1` 时,检查 `a[k-1]` 和 `a[k+1]` 的奇偶性。
* 如果 `total_conflicts - removed_count + added_count == 0`,则说明删除 `a[k]` 后序列是“交替共鸣序列”,答案加一。完整代码
#include<bits/stdc++.h>
using namespace std;
bool panduan(long long a, long long b) {
return (a & 1) == (b & 1);
}
void solve() {
int n;
cin >> n;
vector<long long> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
if (n == 1) {
cout << 1 << endl;
return;
}
vector<bool> conflicts(n - 1, false);
int total_conflicts = 0;
for (int i = 0; i < n - 1; ++i) {
if (panduan(a[i], a[i + 1])) {
conflicts[i] = true;
total_conflicts++;
}
}
int ans = 0;
for (int k = 0; k < n; ++k) {
int removed_count = 0;
int added_count = 0;
if (k > 0 && conflicts[k - 1]) {
removed_count++;
}
if (k < n - 1 && conflicts[k]) {
removed_count++;
}
if (k > 0 && k < n - 1) {
if (panduan(a[k - 1], a[k + 1])) {
added_count++;
}
}
if (total_conflicts - removed_count + added_count == 0) {
ans++;
}
}
cout << ans << endl;
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
评论 (0)