D. Cleaning 前缀后缀
D. Cleaning 前缀后缀
题目大意:
给你一个大小为n的数组,你可以进行一个操作:
- 选择两个相邻的数,如果两个数都大于0,则可以对两个数进行-1的操作
你可以进行一次或者0次特殊操作:
- 选择两个相邻的数,交换他们
题解:
这个题目其实很简单,以前经常写这种类型的题目,但是最近可能很久没有刷题了,居然没有写出来。
这个特殊操作可以进行一次或者0次,那么就枚举这个特殊操作在哪里即可,这个时候我们就要O(1)
判断这个操作是否可行,首先要明白,如果没有这种特殊操作,那么我只需要从前往后判断或者从后往前是否可行即可,但是有这种操作了,枚举 i
和 i+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\n");
else printf("NO\n");
}
return 0;
}