Yet Another Bracket Sequence(线段树&前缀和)
传送门
思路:线段树维护最小前缀和。令
′
(
′
'('
′(′为1,
′
)
′
')'
′)′为
−
1
-1
−1。保证前
n
n
n项和为0且前
n
n
n项最小前缀和大于等于0即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
#define mst(a) memset(a,0,sizeof a)
struct node{
int s,l,r,lz;
}a[N<<2];/// a[x].s 表示 以区间[a[x].l,a[x].r]为下标的最小前缀和.
int pre[N],n,m,sum;
char s[N];
void re(int x){
a[x].s=min(a[x<<1].s,a[x<<1|1].s);
}
void push_down(int x){
if(!a[x].lz) return;
a[x<<1].lz+=a[x].lz,a[x<<1|1].lz+=a[x].lz;
a[x<<1].s+=a[x].lz,a[x<<1|1].s+=a[x].lz;
a[x].lz=0;
}
void build(int x,int l,int r){
a[x].l=l,a[x].r=r;
if(l==r){
a[x].s=pre[l];
return;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
re(x);
}
void change(int x,int l,int r,int val){
if(a[x].l>=l&&a[x].r<=r){
a[x].s+=val;
a[x].lz+=val;
return ;
}
push_down(x);
int mid=(a[x].l+a[x].r)>>1;
if(l<=mid) change(x<<1,l,r,val);
if(r>mid) change(x<<1|1,l,r,val);
re(x);
}
int main(){
scanf("%d%d%s",&n,&m,s+1);
for(int i=1;i<=n;i++) pre[i]=pre[i-1]+((s[i]=='(')?1:-1);
sum=pre[n];
build(1,1,n);
while(m--){
int x;
scanf("%d",&x);
if(s[x]=='(') s[x]=')',change(1,x,n,-2),sum-=2;
else s[x]='(',change(1,x,n,2),sum+=2;
if(a[1].s>=0&&sum==0) puts("Yes");
else puts("No");
}
return 0;
}