BZOJ
考虑询问,如果我们把相互匹配的括号删除,那么我们最终会得到形如)))(的序列。
对于这样一个序列,我们不妨贪心。将左边连续的l个右括号,从第一个到(l+1)/2分别改为左括号。对右边则反之。
那么当l为偶数时,左边会变得合法。当l为奇数时,会多余一个左括号,但由于题目保证了有解,即l+r为偶数,这个多余的左括号将与右边的多余右括号匹配。
这样显然是没有冗余操作的。
这里用了一个小trick,可以只需要维护左右最大子段和即可。
注意replace操作可以覆盖swap和invert操作,因为会使得这两个操作没有意义。
用了无旋treap实现,代码写起来还是短一些。
#include
#include
#include
using namespace std;
const int maxn=100010;
int n,m,sz,rt,a,b,c,ans,val[maxn],rnd[maxn],s[maxn],ch[maxn][2],f[maxn];
int l[maxn],r[maxn],sum[maxn],lazy[maxn],rev[maxn],inv[maxn];
char op[10],ss[maxn];
inline int max(int x,int y){return x>y?x:y;}
inline int min(int x,int y){return xint new_node(char k)//-1->( 1->)
{
s[++sz]=1;rnd[sz]=rand();
if(k=='(') val[sz]=-1;
else val[sz]=1;
return sz;
}
void pushup(int x)
{
s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
l[x]=max(l[ch[x][0]],sum[ch[x][0]]+l[ch[x][1]]+val[x]);
l[x]=max(l[x],sum[ch[x][0]]+val[x]);
r[x]=max(r[ch[x][1]],sum[ch[x][1]]+r[ch[x][0]]+val[x]);
r[x]=max(r[x],sum[ch[x][1]]+val[x]);
}
void pushdown(int x)
{
int L=ch[x][0],R=ch[x][1];
if(lazy[x])
{
if(L)
{
sum[L]=s[L]*lazy[x];lazy[L]=val[L]=lazy[x];
l[L]=r[L]=max(0,sum[L]);inv[L]=rev[L]=0;
}
if(R)
{
sum[R]=s[R]*lazy[x];lazy[R]=val[R]=lazy[x];
l[R]=r[R]=max(0,sum[R]);inv[R]=rev[R]=0;
}
lazy[x]=0;
}
if(inv[x])
{
if(L)
{
int tmp=l[L];
val[L]=-val[L];inv[L]^=1;
l[L]=max(0,-(sum[L]-r[L]));r[L]=max(0,-(sum[L]-tmp));
sum[L]=l[L]+min(0,-sum[L]-l[L]);
}
if(R)
{
int tmp=l[R];
val[R]=-val[R];inv[R]^=1;
l[R]=max(0,-(sum[R]-r[R]));r[R]=max(0,-(sum[R]-tmp));
sum[R]=l[R]+min(0,-sum[R]-l[R]);
}
inv[x]=0;
}
if(rev[x])
{
if(L) rev[L]^=1,swap(l[L],r[L]),swap(ch[L][0],ch[L][1]);
if(R) rev[R]^=1,swap(l[R],r[R]),swap(ch[R][0],ch[R][1]);
rev[x]=0;
}
}
int merge(int x,int y)
{
if(!x||!y){pushup(x+y);return x+y;}
if(lazy[x]||inv[x]||rev[x]) pushdown(x);
if(lazy[y]||inv[y]||rev[y]) pushdown(y);
if(rnd[x]1]=merge(ch[x][1],y);pushup(x);
return x;
}
else
{
ch[y][0]=merge(x,ch[y][0]);pushup(y);
return y;
}
}
void split(int now,int k,int &x,int &y)
{
if(!now){x=y=0;return ;}
if(lazy[now]||inv[now]||rev[now]) pushdown(now);
if(k<=s[ch[now][0]]) y=now,split(ch[now][0],k,x,ch[now][0]);
else x=now,split(ch[now][1],k-s[ch[now][0]]-1,ch[now][1],y);
pushup(now);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int L,R,tmp;
srand(19260817);
scanf("%d%d%s",&n,&m,ss+1);
for(int i=1;i<=n;i++) rt=merge(rt,new_node(ss[i]));
while(m--)
{
scanf("%s%d%d",op,&L,&R);
split(rt,R,a,c);split(a,L-1,a,b);
if(op[0]=='R')
{
scanf("%s",op);
if(op[0]=='(') val[b]=lazy[b]=-1;
else val[b]=lazy[b]=1;
sum[b]=s[b]*lazy[b];l[b]=r[b]=max(0,sum[b]);
rev[b]=inv[b]=0;
}
else if(op[0]=='S') rev[b]^=1,swap(l[b],r[b]),swap(ch[b][0],ch[b][1]);
else if(op[0]=='I')
{
val[b]=-val[b];inv[b]^=1;
tmp=l[b];l[b]=max(0,-(sum[b]-r[b]));r[b]=max(0,-(sum[b]-tmp));
sum[b]=l[b]+min(0,-sum[b]-l[b]);
}
else if(op[0]=='Q')
{
ans=(l[b]+1>>1)+(l[b]-sum[b]+1>>1);
printf("%d\n",ans);
}
rt=merge(merge(a,b),c);
}
return 0;
}