题解1:统计每个括号匹配的位置,统计区间最小和区间最大,如果都在区间内说明是一个有效的序列。
题解2:直接用栈统计,通过记录每个括号进栈时栈的状态,来比较得出是否为有序的序列。
敲了个RMQ的板子
题解1代码(空间和时间其实有点极限)
#include<iostream>
#include<stack>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#define go(i,a,b) for (int i=(a);i<=(b);i++)
#define N 1000010
#define logN 21
using namespace std;
int minn[N][logN],maxn[N][logN],a[N],p[N];
void work(int a[], int n){
memset(minn,0x3f,sizeof(minn));
memset(maxn,0,sizeof(maxn));
for (int i=1;i<=n;i++){
minn[i][0]=a[i];
maxn[i][0]=a[i];
}
for (int j=1;(1<<j)<=n;j++){
for (int i=1;i+(1<<j)-1<=n;i++){
minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l, int r, int c){
if (l>r) swap(l,r);
if (l==r) return p[l];
int len=(r-l+1);
int k=int(log10((double)len)/log10(2.0));
if (!c) return min(minn[l][k],minn[r-(1<<k)+1][k]);
else return max(maxn[l][k],maxn[r-(1<<k)+1][k]);
}
stack<int>stk;
int main(){
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
if (stk.empty()||a[i]%2==0||a[i]%2==1&&a[stk.top()]!=a[i]-1) stk.push(i);
else{
p[stk.top()]=i;
p[i]=stk.top();
stk.pop();
}
}
while (!stk.empty()){
if (a[stk.top()]%2) p[stk.top()]=n+1;
else p[stk.top()]=0;
stk.pop();
}
/*
for (int i=1;i<=n;i++) printf("%d ",p[i]);
cout<<endl;
*/
work(p,n);
int l,r;
while (q--){
scanf("%d%d",&l,&r);
if (query(l,r,0)>=l&&query(l,r,1)<=r) printf("Yes\n");
else printf("No\n");
}
return 0;
}
题解2(比较正解)
#include<iostream>
#include<stack>
#define N 1000050
using namespace std;
int a[N],p[N];
stack<int> stk;
int main(){
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
if (stk.empty()) stk.push(i);
else if (a[stk.top()]==(a[i]^1)&&a[stk.top()]+1==a[i]) stk.pop();
else stk.push(i);
if (!stk.empty()) p[i]=stk.top();
}
int l,r;
while (q--){
scanf("%d%d",&l,&r);
if (p[r]==p[l-1]) printf("Yes\n");
else printf("No\n");
}
return 0;
}