Yet Another Bracket Sequence(線段樹&前綴和)
傳送門
思路:線段樹維護最小前綴和。令爲1, 爲。保證前項和爲0且前項最小前綴和大於等於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;
}