用1表示左括号,-1表示右括号,lmin表示从左开始的最小连续和,rmax表示从右开始的最大连续和,答案为(1-lmin)/2+(1+rmax)/2,splay维护即可。
#include<algorithm>
#include<cstdio>
#define Z(o)(o->i->s1+1)
#define M (i+j>>1)
using namespace std;
const int N=1e5+5;
typedef struct node*ptr;
struct node{
ptr i,j;
int v,t1,t2,t3,s1,s2,s3,s4,s5,s6;
ptr up(){
i->down(),j->down();
s1=i->s1+1+j->s1;
s2=i->s2+v+j->s2;
s3=min(i->s3,i->s2+v+j->s3);
s4=max(i->s4,i->s2+v+j->s4);
s5=min(j->s5,j->s2+v+i->s5);
s6=max(j->s6,j->s2+v+i->s6);
return this;
}
ptr down();
}e[N];
ptr node::down(){
if(this==e)return e;
if(t1){
i->t1=j->t1=v=t1,s2=s1*t1;
if(t1>0)
s3=s5=0,s4=s6=s2;
else
s4=s6=0,s3=s5=s2;
t1=t2=t3=0;
}
if(t2&&t2--){
i->t2^=1,j->t2^=1;
swap(i,j);
swap(s3,s5);
swap(s4,s6);
}
if(t3&&t3--){
i->t3^=1,i->t1*=-1;
j->t3^=1,j->t1*=-1;
v*=-1,s2*=-1;
swap(s3*=-1,s4*=-1);
swap(s5*=-1,s6*=-1);
}
return this;
}
ptr a=e;
ptr pre(char*z,int i,int j){
if(i>j)return e;
node s={pre(z,i,M-1),pre(z,M+1,j),z[M]=='('?1:-1};
return(*++a=s).up();
}
void zig(ptr&o,ptr&s){ptr t=o->i;o->i=s,s=o->up(),o=t;}
void zag(ptr&o,ptr&s){ptr t=o->j;o->j=s,s=o->up(),o=t;}
ptr splay(int v,ptr&o){
ptr s=e,t=e;
while(v!=Z(o->down()))
if(v<Z(o)){
if(v<Z(o->i->down()))
zig(o,o->i->j);
zig(o,s);
}else{
v-=Z(o);
if(v>Z(o->j->down()))
v-=Z(o->j),zag(o,o->j->i);
zag(o,t);
}
while(s!=e)zig(s,o->j);
while(t!=e)zag(t,o->i);
return o->up();
}
ptr&splay(int s,int t,ptr&r){
splay(s,r);
return splay(t-s+2,r->j)->i;
}
int main(){
int n,m,s,t;
static char c,f[N],z[N];
scanf("%d%d%s",&n,&m,f+1);
ptr r=pre(f,0,n+1);
while(m--){
scanf("%s%d%d",z,&s,&t);
ptr o=splay(s,t,r);
if(*z=='R')
scanf(" %c",&c),o->t1=c=='('?1:-1;
if(*z=='S')o->t2=1;
if(*z=='I')o->t3=1;
if(*z=='Q')
printf("%d\n",(1-o->s3)/2+(1+o->s6)/2);
}
}