codeforces1474D Cleaning(找出数学公式的规律)

传送门
题解:刚开始想的简单了,觉得因为最多只交换一次么,那么从左到右考虑,如果左边消不完,那么考虑当前位和下一位换,要么就是下一位和下下一位换,简直是搞笑,再深入思考下,因为无论每次交换哪两个,都得从左向右考虑消除,这样就有点想法,如果这些交换在 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[i1]=a[i]a[i1]+
也就是挨个消除的值,可以发现如果每个 b [ 1 − ( n − 1 ) ] b[1-(n-1)] b[1(n1)] > = 0 >= 0 >=0 的话并且最后 b [ n − 1 ] = = 0 b[n-1]==0 b[n1]==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;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/112863004