传送门
题解:刚开始想的简单了,觉得因为最多只交换一次么,那么从左到右考虑,如果左边消不完,那么考虑当前位和下一位换,要么就是下一位和下下一位换,简直是搞笑,再深入思考下,因为无论每次交换哪两个,都得从左向右考虑消除,这样就有点想法,如果这些交换在 O ( 1 ) O(1) O(1) 时间能维护出来,那么岂不是能判断出来了,可以用个 b b b 数组这样考虑
b [ 0 ] = a [ 0 ] b [ 1 ] = a [ 1 ] − b [ 0 ] b [ 2 ] = a [ 2 ] − b [ 1 ] = a [ 2 ] − a [ 1 ] + a [ 0 ] … b [ i ] = a [ i ] − b [ i − 1 ] = a [ i ] − a [ i − 1 ] + … b[0]=a[0]\\ b[1]=a[1]-b[0]\\ b[2]=a[2]-b[1]=a[2]-a[1]+a[0]\\ \dots\\ b[i]=a[i]-b[i-1]=a[i]-a[i-1]+\dots\\ b[0]=a[0]b[1]=a[1]−b[0]b[2]=a[2]−b[1]=a[2]−a[1]+a[0]…b[i]=a[i]−b[i−1]=a[i]−a[i−1]+…
也就是挨个消除的值,可以发现如果每个 b [ 1 − ( n − 1 ) ] b[1-(n-1)] b[1−(n−1)] 都 > = 0 >= 0 >=0 的话并且最后 b [ n − 1 ] = = 0 b[n-1]==0 b[n−1]==0 的话那么就是合法的消除,现在考虑如果交换 i , j i,j i,j 带来的影响,首先对于 i i i 以前的 b b b 值都不会带来影响,对于 b [ i ] b[i] b[i] 造成的影响就是 a [ i ] a[i] a[i] 的变化, 对于 i i i 后面的 b b b 值带来的影响是 a [ i ] , a [ i + 1 ] a[i],a[i+1] a[i],a[i+1] 分别的变化所带来的影响,里边涉及奇偶性的问题,细节挺多,对于 i i i 后面带来的影响我们只需要提前打个后缀 b b b 的最小值表即可。
里面细节很多,我写的也比较繁琐,好在过了,不然又是调老长时间。
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
const int inf = 0x3f3f3f3f;
int n, a[N], b[N], pre[N][2], suf[N][2];
int main()
{
int T;
cin >> T;
while (T--) {
cin >> n;
for(int i = 0; i < n; i++) {
cin >> a[i];
if (i == 0) {
b[i] = a[i];
} else {
b[i] = a[i] - b[i - 1];
}
for (int j = 0; j < 2; j++) {
pre[i][j] = suf[i][j] = inf;
}
}
pre[0][0] = b[0]; suf[n - 1][(n - 1) % 2] = b[n - 1];
for (int i = 1; i < n; i++) {
if (i % 2 == 0) {
pre[i][0] = min(pre[i - 1][0], b[i]);
pre[i][1] = pre[i - 1][1];
} else {
pre[i][1] = min(pre[i - 1][1], b[i]);
pre[i][0] = pre[i - 1][0];
}
}
for (int i = n - 2; i >= 0; i--) {
if (i % 2 == 0) {
suf[i][0] = min(suf[i + 1][0], b[i]);
suf[i][1] = suf[i + 1][1];
} else {
suf[i][1] = min(suf[i + 1][1], b[i]);
suf[i][0] = suf[i + 1][0];
}
}
bool flag = false;
if (b[n - 1] == 0 && pre[n - 1][0] >=0 && pre[n - 1][1] >= 0) {
flag = true;
} else {
for (int i = 0; i < n; i++) {
if (i - 1 >= 0 && (pre[i - 1][0] < 0 || pre[i - 1][1] < 0)) {
flag = false;
break;
} else {
int c0 = a[i + 1] - a[i], c1 = (i % 2 == 0 ? 2 * c0 : -2 * c0), c2 = b[n - 1] + ((n - 1) % 2 == 0 ? c1 : -1 * c1);
// cout << i << " " << c0 << " " << c1 << " " << c2 << " " << suf[i][0] + c1 << " " << suf[i][1] - c1 << endl;
if (c2 == 0 && suf[i + 1][0] + c1 >= 0 && suf[i + 1][1] - c1 >= 0 && b[i] + c0 >= 0) {
flag = true;
break;
}
}
}
}
cout << (flag ? "YES" : "NO") << endl;
}
return 0;
}