D. Cleaning (good thinking questions + prefix)

https://codeforces.com/contest/1474/problem/D


The meaning of the question: n numbers, now you can take out the adjacent numbers that are not 0, so that they are reduced by 1 at the same time. If a heap is 0, it will not disappear. At this time, we have at most one opportunity to operate. Swap the positions of two adjacent numbers and ask if you can make all the numbers become 0.

Idea: First find that the endpoint must be <= the following value, otherwise it is definitely not true.

So a2>=a1, after subtraction, a2=a2-a1; at this time, a2 becomes the end point, and the same principle shows that a3>= can only be established at this time.

So the same applies to starting from the tail.

Then use a prefix to record the intermediate process. That is, the prefix is ​​used to indicate that the adjacent ones can be subtracted, then how much the number behind becomes at this time. The suffix is ​​the same.

If you encounter pre[i-1]>a[i] halfway, then it means that if you subtract these two adjacent ones, it will cause a[i-1] to become an "empty island", Cannot meet the requirements of the subject. In this case, the record is pre[i]=inf/2; [Why/2, because this is also the case at the beginning of the back end, and it is necessary to judge whether the prefix and suffix are equal when exchanging adjacent items. And if suf[]=inf/2, the two numbers that cannot be equal become inf=inf-leading to wrong judgment]

Then enumerate to determine whether the prefix and suffix pre[i] and suf[i+1] are the same. The same is fine. Try to exchange differently, see if you can.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef long long LL;
LL a[maxn],pre[maxn],suf[maxn];
const LL inf=1e18;
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL t;cin>>t;
  while(t--){
    LL n;cin>>n;
    for(LL i=0;i<=n+10;i++) pre[i]=suf[i]=0;
    for(LL i=1;i<=n;i++) cin>>a[i];
    for(LL i=1;i<=n;i++){
        if(a[i]>=pre[i-1]){
            pre[i]=a[i]-pre[i-1];
        }
        else pre[i]=inf/2;
    }
    for(LL i=n;i>=1;i--){
        if(a[i]>=suf[i+1]){
            suf[i]=a[i]-suf[i+1];
        }
        else suf[i]=inf;
    }
    bool flag=1;
    for(LL i=1;i<=n-1;i++){
        if(pre[i]==suf[i+1]){
            flag=0;
            break;
        }
        else{
            ///交换相邻石堆
            LL A=a[i];LL B=a[i+1];
            if(A>=suf[i+2]&&B>=pre[i-1]){
                A-=suf[i+2];B-=pre[i-1];
                LL cnt=A-B;
                if(cnt==0){
                    flag=0;
                    break;
                }
            }
        }
    }
    if(flag==0){
        cout<<"YES"<<endl;
    }
    else cout<<"NO"<<endl;
  }
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/112862389