cf1474D

标签给的是DP但是又双叒叕和DP没有关系。

这道题读一会儿之后就会自然而然的感觉和前缀后缀有关系。因为如果能够相邻的正好两两相消,那么我们不管从前往后还是从后往前,两两相减一定正好消完,那么除了问题就说明中间的某一处对不上了。但是他的前面和后面都是对的(因为只能换一组,如果前后还有问题那说明要换的不止一组,肯定不行了)。做一个前缀再做一个后缀,然后枚举一下交换两个之后能否相消。如果相消了那就说明对了。

这里要注意,对上的时候要看一下是不是负数相消,因为移石头不可能是负的,所以负数对负数消掉了也没用,还是NO,这点前面没发现WA了好久,叹气。

下附代码:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 ll a[200005],n;
 5 ll st[200005],ed[200005],stf[200005],edf[200005];
 6 int main(){
 7     int T;
 8     scanf("%d",&T);
 9     while (T--){
10         scanf("%lld",&n);
11         for (int i=1; i<=n; i++){
12             scanf("%lld",&a[i]);
13         }
14         ed[n+1]=0;
15         for (int i=n; i>=1; i--){
16             if (ed[i+1]==-1 || a[i]<ed[i+1]){
17                 ed[i]=-1;
18             }
19             else {
20                 ed[i]=a[i]-ed[i+1];
21             }
22         }
23         st[0]=0;
24         for (int i=1; i<=n; i++){
25             if (st[i-1]==-1 || a[i]<st[i-1]){
26                 st[i]=-1;
27             }
28             else {
29                 st[i]=a[i]-st[i-1];
30             }
31         }
32         int flag=0;
33         if (st[n]==0) {
34             printf("YES
");
35             flag=1;
36         }
37         else {
38             for (int i=1; i<=n-1; i++){
39                if (st[i-1]==-1 || ed[i+2]==-1) continue;
40                if (a[i+1]>=st[i-1] && a[i]>=ed[i+2] && a[i+1]-st[i-1]==a[i]-ed[i+2]){
41                    printf("YES
");
42                    flag=1;
43                    break;
44                }
45             }
46         }
47         if (!flag) printf("NO
");
48     }
49 }
View Code
原文地址:https://www.cnblogs.com/i-caigou-TT/p/14340471.html