1. 程式人生 > >CF1092 D Great Vova Wall —— 思路+單調棧

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