CF1092 D Great Vova Wall —— 思路+单调栈

题目:https://codeforces.com/contest/1092/problem/D1

https://codeforces.com/contest/1092/problem/D2

很有趣的题;

对于D1,首先发现两种砖的放法和高度的奇偶性有关(!);

而竖着放的砖不改变一列的奇偶性,也就是确定一列的奇偶性后,它的高度是可以任意的,那么我们就不用考虑实际高度的问题了;

然后发现,如果两列奇偶性相同的列相邻了,那么它们就“无敌”了,可以变成任意高度;

而两列可以合并,只能是它们相邻且奇偶性相同;

这就很像两组括号序列啊!奇数是 (),偶数是 [],那么整个序列就是 (, ), [, ] 相间的;

只要栈顶能完成一个匹配,就弹栈表示这两列“无敌”了;

所以最后要是栈里没有元素或只剩下一个元素,序列就是合法的,否则不合法;

这么简单就做完了!

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=2e5+5;
int n,sta[xn],top;
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return f?ret:-ret;
}
int main()
{
  n=rd();
  for(int i=1,x;i<=n;i++)
    {
      x=rd();
      if(top&&(x&1)==(sta[top]&1))top--;
      else sta[++top]=x;
    }
  if(top<=1)puts("YES");
  else puts("NO");
  return 0;
}
D1

对于D2,只能放横着的砖;

那就更简单了,每次先填满最低的一段,如果其长度是奇数就不合法了,否则就和旁边的合并成一段;

这个过程可以用单调栈维护。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int const xn=2e5+5;
int n,sta[xn],top,len[xn],a[xn];
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return f?ret:-ret;
}
int main()
{
  n=rd();
  for(int i=1;i<=n;i++)a[i]=rd(); 
  for(int i=1,l,j;i<=n;i=j+1)
    {
      j=i; l=0;
      while(a[i]==a[j+1])j++;
      while(top&&a[i]>sta[top])
    {
      if(len[top]&1){puts("NO"); return 0;}
      l=len[top]; top--;
      if(top&&sta[top]<a[i])len[top]+=l;
      else break;
    }
      while(top&&sta[top]==a[i])l+=len[top--];
      sta[++top]=a[i]; len[top]=l+(j-i+1);
      //printf("sta[%d]=%d len=%d\n",top,sta[top],len[top]);
    }
  int l=0;
  while(top>1)
    {
      l+=len[top--];
      if(l&1){puts("NO"); return 0;}
    }
  puts("YES");
  return 0;
}
D2

猜你喜欢

转载自www.cnblogs.com/Zinn/p/10159357.html