CF1610B [Kalindrome Array]

发布时间 2023-10-11 22:18:37作者: yhx0322

Problem

题目简述

给你一个数列 \(a\),有这两种情况,这个数列是「可爱的」。

  • 它本身就是回文的。
  • 定义变量 \(x\),满足:序列 \(a\) 中所有值等于 \(x\) 的元素删除之后,它是回文的。

思路

首先考虑暴力。暴力枚举数组中的每一个数,当作变量 \(x\),然后进行回文检验。

时间复杂度 \(O(n^2)\),严重超时。

然后考虑如何优化。

根据回文判断的方法,我们很容易想到:双指针的优化。

设变量 \(l\)\(r\),初始值分别为 \(1\)\(n\)。如果扫描到 a[l] != a[r] 的情况,用两个变量记录一下它们的值,然后停止循环。

然后删除 \(a\) 数组中值为 \(a_l\) 或者是 \(a_r\) 的数字,看看删除之后是否满足回文的条件。

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 10;
int t, n, a[N], tmp[N];

bool ishuiwen(int n, int b[]) { // 是否是回文
	for (int i = 1; i <= n; i++) {
		if (b[i] != b[n - i + 1]) return false;
	}
	return true;
}

bool check(int x) { // 检验删除值为x的情况下是否满足回文
	int idx = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i] != x) tmp[++idx] = a[i];
	}
	return ishuiwen(idx, tmp);
}

int main() {
	scanf("%d", &t);
	while (t--) {
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		if (ishuiwen(n, a)) { // 本身就满足条件
			printf("YES\n");
			continue;
		}
		int l = 1, r = n, x, y;
		while (l <= r) {
			if (a[l] != a[r]) { // 不满足,删数字
				x = a[l], y = a[r];
				break;
			} else l++, r--;
		}
		if (check(x) || check(y)) printf("YES\n"); // 只要一个满足条件就可以
		else printf("NO\n");
	}
	return 0;
}