先呈上原题链接 Princess Principal
这是2018年牛客网国庆集训的题目,不会也没补,后来准备参加 秦皇岛 CCPC - Winter Camp 时在第一场热身赛时又遇到了。当时热身赛都过了一半了才想起这个事,在图书馆把签到题写了,刚看到这道题就被室友叫去打篮球了。虽然一直牵挂到这道题,直到今天才补上。。。
算是一道比较经典的括号序列题了吧。
题意:
要快速判断一个文档有没有语法错误。
有一个含有 n n n 个括号的文档。括号一共有 m m m 种,每种括号都有左括号和右括号两种形式,其中偶数为左括号,奇数为右括号,且 ⌊ x 2 ⌋ \lfloor \frac{x}{2} \rfloor ⌊2x⌋ 相等时为同一种括号。如 0 2 3 1 0\space 2 \space3 \space1 0 2 3 1 为合法的括号序列,而 1 0 2 3 1 \space0 \space2 \space3 1 0 2 3 为非法的括号序列。
我们定义用如下的方式定义一个合法的文档:
1.一个空的字符串是一个合法的文档。
2.如果 A , B A,B A,B 都是合法的文档,那么 A B AB AB 也是合法的文档。
3.如果 S S S 是合法的文档,那么 a S b aSb aSb 也是合法的文档,其中 a , b a,b a,b 是同一种括号,并且 a a a 是左括号, b b b 是右括号。
现在给出 q q q 个询问,每次询问只考虑文档第 l l l 至 r r r 个字符的情况下,文档是不是合法的。
思路:
坑点:
无
good luck and have fun!!!
附上代码:
#include
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define test(flag,value) cout<
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DB;
const int INF=0x3f3f3f3f;
const int MAXN=1e6;
const double PI=acos(-1);
const int MOD=1e9+7;
int minn[MAXN<<2],maxx[MAXN<<2],a[MAXN],b[MAXN];
void push_up(int rt)
{
minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
maxx[rt]=max(maxx[rt<<1],maxx[rt<<1|1]);
}
void build(int rt,int l,int r)
{
if(l==r)
{
minn[rt]=b[l];
maxx[rt]=b[l];
return;
}
int m=(l+r)>>1;
build(rt<<1,l,m);
build(rt<<1|1,m+1,r);
push_up(rt);
}
int query1(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return minn[rt];
int m=(l+r)>>1;
int x1=INF,x2=INF;
if(m>=L) x1=query1(L,R,l,m,rt<<1);
if(m<R) x2=query1(L,R,m+1,r,rt<<1|1);
return min(x1,x2);
}
int query2(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return maxx[rt];
int m=(l+r)>>1;
int x1=0,x2=0;
if(m>=L) x1=query2(L,R,l,m,rt<<1);
if(m<R) x2=query2(L,R,m+1,r,rt<<1|1);
return max(x1,x2);
}
stack<int> S;
stack<int> S2;
int main(void)
{
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
while(!S.empty())S.pop();
while(!S2.empty())S2.pop();
for(int i=1;i<=n;i++)
{
if(S.empty())
{
S.push(a[i]);
S2.push(i);
}
else if(S.top()==a[i]-1&&a[i]%2==1)
{
int x=S2.top();
b[x]=i;
b[i]=x;
S.pop();S2.pop();
}
else
{
S.push(a[i]);
S2.push(i);
}
}
while(!S2.empty())
{
int x=S2.top();
b[x]=-1;
S2.pop();
}
build(1,1,n);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
int y1=query1(l,r,1,n,1);
int y2=query2(l,r,1,n,1);
if(y1<l||y2>r)
printf("No\n");
else
printf("Yes\n");
}
}