D. Cleaning 前缀后缀

D. Cleaning 前缀后缀

题目大意:

给你一个大小为n的数组,你可以进行一个操作:

  • 选择两个相邻的数,如果两个数都大于0,则可以对两个数进行-1的操作

你可以进行一次或者0次特殊操作:

  • 选择两个相邻的数,交换他们

题解:

这个题目其实很简单,以前经常写这种类型的题目,但是最近可能很久没有刷题了,居然没有写出来。

这个特殊操作可以进行一次或者0次,那么就枚举这个特殊操作在哪里即可,这个时候我们就要O(1) 判断这个操作是否可行,首先要明白,如果没有这种特殊操作,那么我只需要从前往后判断或者从后往前是否可行即可,但是有这种操作了,枚举 ii+1 ,那么我判断 i-1 往前和 i+2 往后都是可行的即可。然后再 O(1) 判断这个交换操作的可行性。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int pre[maxn],suffer[maxn],a[maxn];
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=0;i<=n+10;i++) pre[i] = suffer[i] = 0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            if(a[i]>=pre[i-1]) pre[i] = a[i] - pre[i-1];
            else pre[i] = inf;
        }
        for(int i=n;i>=1;i--){
            if(a[i]>=suffer[i+1]) suffer[i] = a[i] - suffer[i+1];
            else suffer[i] = inf;
        }
        bool flag = false;
        if(pre[n]==0||suffer[1]==0) flag = true;
        for(int i=1;i<n;i++){
            if(pre[i]!=inf&&pre[i]==suffer[i+1]) flag = true;
            if(a[i+1]>=pre[i-1]&&a[i]>=suffer[i+2]&&a[i+1]-pre[i-1]==a[i]-suffer[i+2]) flag = true;
        }
        if(flag) printf("YES
");
        else printf("NO
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/EchoZQN/p/14315046.html