BZOJ2329: [HNOI2011]括号修复
用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); } }