2018牛客国庆集训派对day1 J Princess Principal(思维or线段树,RMQ)

题意大致是给出一个括号序列,然后给出多组询问,每次判断一个区间里的括号是否是匹配的。

具体可见

这里给出两种做法。

对于一个括号序列,如果我们想让所有的括号尽可能多的匹配,每个单括号应该只对应唯一的另一个单括号与它匹配。那么我们就可以比较加入a[l]之前栈里留下的括号的状态,和加入a[r]以后栈里留下的括号的状态,如果一样,相当于这段区间的括号"消掉了",也就是这段区间是匹配的。

另一种想法:既然我们要判断的是一个区间里的括号是否是匹配,那么我们已经知道括号序列的匹配方式是唯一的,如果我们在区间里任意取出一个单括号,与它匹配的单括号也必须在这个区间里,否则这个区间的括号是不匹配的,这种性质我把它称为"封闭性"。  所以我们先预处理与每一个位置单括号匹配的另一个单括号的编号x[i]。  但是即使我们预处理完了以后,查询一个区间的复杂度仍然是线性的。 但其实我们只需要查询这个区间里x[i]的最大值和最小值即可,最大值是右端点,最小值是左端点说明这个区间是封闭的,即匹配的(这里可能会出现有的单括号根本找不到匹配的单括号的情况,所以预处理的时候请把这些括号的x[i]设置为-1),否则必然不是匹配的。查询最值线段树或RMQ都可。

2种方法的具体代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int n,m,q;
int a[maxn],x[maxn];
stack<int>s;
int main()
{
    scanf("%d %d %d",&n,&m,&q);
    while(!s.empty()) s.pop();
    for(int i=1;i<=n;i++)
        scanf("%d",a+i);
    for(int i=1;i<=n;i++)
    {
        if(s.empty()||!(a[i]&1))
            s.push(i);
        else if(a[s.top()]+1==a[i])
            s.pop();
        else s.push(i);
        if(s.empty()) x[i]=0;
        else x[i]=s.top();
    }
    while(q--)
    {
     int l,r;
     scanf("%d %d",&l,&r);
     if(x[l-1]==x[r])
        printf("Yes\n");
     else printf("No\n");
    }
    return 0;
}
  #include<bits/stdc++.h>
  using namespace std;
  const int maxn=1e6+5;
  int n,m,q;
  int a[maxn],b[maxn],x[maxn<<2],y[maxn<<2];
  stack<int>s;
  void build(int R,int l,int r)
  {
     if(l==r)
     {
         x[R]=b[l];
         y[R]=b[l];
         return;
     }
     int mid=l+r>>1;
     build(R<<1,l,mid);
     build(R<<1|1,mid+1,r);
     x[R]=min(x[R<<1],x[R<<1|1]);
     y[R]=max(y[R<<1],y[R<<1|1]);
  }
  void ask(int R,int l,int r,int ql,int qr,int &u,int &v)
  {
      if(ql<=l&&r<=qr)
      {
        u=min(u,x[R]);
        v=max(v,y[R]);
        return ;
      }
      int mid=l+r>>1;
      if(ql<=mid) ask(R<<1,l,mid,ql,qr,u,v);
      if(qr>mid) ask(R<<1|1,mid+1,r,ql,qr,u,v);
  }
  int main()
  {
      scanf("%d %d %d",&n,&m,&q);
      for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            b[i]=-1;
            if(s.empty()||!(a[i]&1)) s.push(i);
            else if (a[s.top()]+1==a[i]) b[i]=s.top(),b[s.top()]=i,s.pop();
            else  s.push(i);
        }
      build(1,1,n);
      while(q--)
      {
          int ql,qr;
          scanf("%d %d",&ql,&qr);
          int _1=1e9,_2=-2;
          ask(1,1,n,ql,qr,_1,_2);
          if(_1==ql&&_2==qr)
            puts("Yes");
          else puts("No");
      }
      return 0;
  }

猜你喜欢

转载自blog.csdn.net/zero___zero/article/details/82924088
今日推荐