D1. Great Vova Wall (Version 1):
题意:给定长度为N的墙,以及每个位置的一些高度,现在让你用1*2的砖和2*1的砖去铺,问最后能否铺到高度一样。
思路:分析其奇偶性,在一个位置加1*2的砖,其奇偶性不变。在相邻的而且高度相同的位置加2*1的砖,两个奇偶行都改变。那么我们不需要保存高度,因为高度我们可以加1*2的砖,使他们等效到奇偶性的高度;所以只需要保存奇偶,然后加入栈中,如果栈顶的两个元素相同,则可以消去,最后如果栈元素<=1,则ok。
(如果最后栈为空,说明最后高度可奇可以偶;否则,最后的高度由栈里剩下的一个元素奇偶性决定。

#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; int a[maxn],q[maxn],top; bool get(int N) { top=0; for(int i=1;i<=N;i++){ q[++top]=a[i]; if(top>=2&&q[top]==q[top-1]) top-=2; } if(top<=1) return true; return false; } int main() { int N; scanf("%d",&N); rep(i,1,N) scanf("%d",&a[i]),a[i]=a[i]&1; if(get(N)) return puts("YES"),0; puts("NO"); return 0; }
D2. Great Vova Wall (Version 2)
题意:和上面一样,只是现在只能铺2*1的砖。
思路:开始想简单了,以为是贪心即可,比如1,3,2,贪心出来可以铺,错的。事后想还是应该用栈去做。
还是用消去的思想去想,如果连续的两个相同,我们就可以消去;如果我在中间消去了一段,那么这一段的两边可以拼接起来,那么如果这两边的相同,我们是否也可以消去了呢?不一定,比如1,2,2,1;我们消去了(2,2),不可以消去(1,1);原因是被中间的更高的阻断了,我们所以维护栈的时候记录以下中间的消去的值,如果比栈顶的大,则栈顶暂时不能消去。
(而D1不需要考虑这个问题,是因为D1的高度没什么约束性,只考虑奇偶。

#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2000010; int a[maxn],Mx,q[maxn],h[maxn],top; int main() { int N; scanf("%lld",&N); rep(i,1,N) scanf("%d",&a[i]),Mx=max(Mx,a[i]); rep(i,1,N) { q[++top]=a[i]; if(top>1&&q[top]==q[top-1]){ if(q[top]<h[top-1]) continue; top-=2,h[top]=q[top+1]; h[top+1]=0; h[top+2]=0; } } if(top==0||(top==1&&q[top]==Mx)) puts("YES"); else puts("NO"); return 0; }