#最大公因数 #前缀和 先预处理 $\gcd(a_i, a_{i+1})$,存进 $b_i$,然后枚举删第 $i$ 个数,那么 $i$ 前面的相邻的最大公因数以及 $i$ 后面的相邻的最大公因数就必须递增。既然将 $i$ 删掉了,那么补充的元素就是 $\gcd(a_{i-1},a_{i+1})$,需要位于上一个 $b_i$ 和下一个 $b_i$ 的中间。 怎样快速求前缀或后缀 $b_i$ 都是单调非递增或单调非递减的呢?以前缀单调非递减举例,令 $p_i$ 表示 $1\sim i$ 当中的所有 $b_i$ 是否递增,那么求 $p_i$ 的时候如果 $p_{i-1}=0$ 就当然不满足条件啦,如果为真就看一下 $b_i$ 是否大于等于 $b_{i-1}$ 就行了。 ```cpp #include <iostream> using namespace std; const int kMaxN = 2e5 + 5; int a[kMaxN], b[kMaxN], p[kMaxN], s[kMaxN], t, n, ans; int gcd(int n, int m) { return !m ? n : gcd(m, n % m); } int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); for (cin >> t; t; t--) { cin >> n, ans = 0; for (int i = 1; i <= n; i++) { cin >> a[i]; } p[0] = s[n] = 1, b[n] = 1e9; for (int i = 1; i < n; i++) { b[i] = gcd(a[i], a[i + 1]); p[i] = p[i - 1] && b[i] >= b[i - 1]; } for (int i = n - 1; i; i--) { s[i] = s[i + 1] && b[i] <= b[i + 1]; } for (int i = 1; i <= n; i++) { ans |= (i <= 2 || p[i - 2]) && (i >= n || s[i + 1]) && (i == 1 || i == n || (b[i - 2] <= gcd(a[i - 1], a[i + 1]) && gcd(a[i - 1], a[i + 1]) <= b[i + 1])); } cout << (ans ? "YES" : "NO") << '\n'; } return 0; } ```