这个题有一点非常重要,就是任意一个非法的序列,我们在它的左边添加若干个"(",右边添加若干个")",那么一定能够变成一个合法的序列。
在这里就不证明了,比如"()))((",我们在它的左边添加两个"(",右边两个")",序列变成"((()))(())",就成了一个合法的序列了!
因此在每一个区间,我们记录它缺少的左括号数needl,缺少的右括号数needr,那么区间合并的问题就解决了。
这个题还有一个反号操作,因此我们还要记录每个区间反号以后缺少的左括号数tneedl,缺少的右括号数tneedr。
reverse的时候交换一下这两个值就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define N 200005
struct node
{
int set,rev;
int needl,needr;
int tneedl,tneedr;
}seg[N<<2];
int n,q;
char str[N];
void fset(int l,int r,int index,int flag)
{
seg[index].set=flag;
seg[index].rev=0;
if(flag==1)//左括号
{
seg[index].needl=seg[index].tneedr=0;
seg[index].needr=seg[index].tneedl=r-l+1;
}
else//右括号
{
seg[index].needl=seg[index].tneedr=r-l+1;
seg[index].needr=seg[index].tneedl=0;
}
}
void frev(int l,int r,int index)
{
seg[index].rev^=1;
swap(seg[index].needl,seg[index].tneedl);
swap(seg[index].needr,seg[index].tneedr);
}
void pushup(int l,int r,int index)
{
node& father=seg[index];
node& lson=seg[index<<1];
node& rson=seg[index<<1|1];
father.needl=lson.needl;
father.needr=rson.needr;
if(lson.needr>rson.needl)father.needr+=lson.needr-rson.needl;
else father.needl+=rson.needl-lson.needr;
father.tneedl=lson.tneedl;
father.tneedr=rson.tneedr;
if(lson.tneedr>rson.tneedl)father.tneedr+=lson.tneedr-rson.tneedl;
else father.tneedl+=rson.tneedl-lson.tneedr;
}
void pushdown(int l,int r,int index)
{
int m=(l+r)>>1;
node& father=seg[index];
node& lson=seg[index<<1];
node& rson=seg[index<<1|1];
if(father.set)
{
fset(lc,father.set);
fset(rc,father.set);
father.set=0;
}
if(father.rev)
{
frev(lc);
frev(rc);
father.rev=0;
}
}
void build(int l,int r,int index)
{
seg[index].set=seg[index].rev=0;
if(l==r)
{
if(str[l]=='(')
{
seg[index].needl=seg[index].tneedr=0;
seg[index].needr=seg[index].tneedl=1;
}
else
{
seg[index].needl=seg[index].tneedr=1;
seg[index].needr=seg[index].tneedl=0;
}
return;
}
int m=(l+r)>>1;
build(lc);
build(rc);
pushup(l,r,index);
}
void updataset(int L,int R,int flag,int l,int r,int index)
{
if(L==l&&R==r)
{
fset(l,r,index,flag);
return;
}
pushdown(l,r,index);
int m=(l+r)>>1;
if(R<=m)updataset(L,R,flag,lc);
else if(L>m)updataset(L,R,flag,rc);
else
{
updataset(L,m,flag,lc);
updataset(m+1,R,flag,rc);
}
pushup(l,r,index);
}
void updatarev(int L,int R,int l,int r,int index)
{
if(L==l&&R==r)
{
frev(l,r,index);
return;
}
pushdown(l,r,index);
int m=(l+r)>>1;
if(R<=m)updatarev(L,R,lc);
else if(L>m)updatarev(L,R,rc);
else
{
updatarev(L,m,lc);
updatarev(m+1,R,rc);
}
pushup(l,r,index);
}
node query(int L,int R,int l,int r,int index)
{
if(L==l&&R==r)return seg[index];
pushdown(l,r,index);
int m=(l+r)>>1;
if(R<=m)return query(L,R,lc);
else if(L>m)return query(L,R,rc);
else
{
node lson,rson,father;
lson=query(L,m,lc);
rson=query(m+1,R,rc);
father.needl=lson.needl;
father.needr=rson.needr;
if(lson.needr>rson.needl)father.needr+=lson.needr-rson.needl;
else father.needl+=rson.needl-lson.needr;
return father;
}
}
int main()
{
int t,tcase=1,a,b;
node ans;
char op[25],temp[25];
scanf("%d",&t);
while(t--)
{
printf("Case %d:\n",tcase++);
scanf("%d%s%d",&n,str,&q);
build(0,n-1,1);
while(q--)
{
scanf("%s%d%d",op,&a,&b);
if(op[0]=='q')
{
ans=query(a,b,0,n-1,1);
if(ans.needl==0&&ans.needr==0)printf("YES\n");
else printf("NO\n");
}
else if(op[0]=='s')
{
scanf("%s",temp);
if(temp[0]=='(')updataset(a,b,1,0,n-1,1);
else updataset(a,b,2,0,n-1,1);
}
else updatarev(a,b,0,n-1,1);
}
printf("\n");
}
return 0;
}