【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列
题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作,还要维护左边有多少多余的左括号,右边有多少多余的右括号(如果一个右括号匹配一个左括号的话)。然后xjb维护一番即可。。。
答案是什么呢?$lceil{左边多余的右括号数over 2} ceil+lceil{右边多余的左括号数over 2} ceil$。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn=100010; int n,m,rt; struct node { int v,f[2][2],ch[2],fa,siz,tag; bool r1,r2; }s[maxn]; char str[maxn]; //'('->0 ')'->1 r1->反 r2->翻 inline int ab(const int &a) {return a>0?a:0;} inline void pushup(int x) { int l=s[x].ch[0],r=s[x].ch[1]; s[x].siz=s[l].siz+s[r].siz+1; s[x].f[0][0]=s[l].f[0][0]+ab(s[r].f[0][0]-s[x].v-s[l].f[1][1]); s[x].f[1][1]=s[r].f[1][1]+ab(s[l].f[1][1]+s[x].v-s[r].f[0][0]); s[x].f[0][1]=s[l].f[0][1]+ab(s[r].f[0][1]+s[x].v-s[l].f[1][0]); s[x].f[1][0]=s[r].f[1][0]+ab(s[l].f[1][0]-s[x].v-s[r].f[0][1]); } inline void rev1(int x) { s[x].tag=-s[x].tag,s[x].v=-s[x].v,s[x].r1^=1,swap(s[x].f[0][0],s[x].f[0][1]),swap(s[x].f[1][0],s[x].f[1][1]); } inline void rev2(int x) { s[x].r2^=1,swap(s[x].ch[0],s[x].ch[1]),swap(s[x].f[0][0],s[x].f[1][0]),swap(s[x].f[0][1],s[x].f[1][1]); } inline void cover(int x,int y) { s[x].tag=s[x].v=y,s[x].f[0][y>0]=s[x].f[1][y>0]=s[x].siz,s[x].f[0][y<0]=s[x].f[1][y<0]=0,s[x].r1=s[x].r2=0; } inline void pushdown(int x) { int l=s[x].ch[0],r=s[x].ch[1]; if(s[x].tag) { if(l) cover(l,s[x].tag); if(r) cover(r,s[x].tag); s[x].tag=0; } if(s[x].r1) { if(l) rev1(l); if(r) rev1(r); s[x].r1=0; } if(s[x].r2) { if(l) rev2(l); if(r) rev2(r); s[x].r2=0; } } inline void rotate(int x,int &k) { int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]); if(y!=k) s[z].ch[y==s[z].ch[1]]=x; else k=x; s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1]; if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y; s[x].ch[d^1]=y; pushup(y),pushup(x); } inline void splay(int x,int &k) { while(x!=k) { int y=s[x].fa,z=s[y].fa; if(y!=k) { if((x==s[y].ch[0])^(y==s[z].ch[0])) rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int x,int y) { if(!x) return 0; pushdown(x); if(s[s[x].ch[0]].siz>=y) return find(s[x].ch[0],y); if(s[s[x].ch[0]].siz+1<y) return find(s[x].ch[1],y-s[s[x].ch[0]].siz-1); return x; } inline void split(int a,int b) { splay(find(rt,a),rt),splay(find(rt,b+2),s[rt].ch[1]); } int build(int l,int r) { if(l>r) return 0; int x=(l+r)>>1; s[x].ch[0]=build(l,x-1),s[x].ch[1]=build(x+1,r); if(s[x].ch[0]) s[s[x].ch[0]].fa=x; if(s[x].ch[1]) s[s[x].ch[1]].fa=x; pushup(x); return x; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar(); return ret*f; } int main() { //freopen("bz2329.in","r",stdin); n=rd(),m=rd(); int i,a,b,x; scanf("%s",str+1); for(i=1;i<=n;i++) s[i+1].v=(str[i]=='(')?-1:1; rt=build(1,n+2); for(i=1;i<=m;i++) { scanf("%s",str),a=rd(),b=rd(),split(a,b),x=s[s[rt].ch[1]].ch[0]; if(str[0]=='R') { scanf("%s",str); cover(x,(str[0]=='(')?-1:1),pushup(s[x].fa),pushup(s[s[x].fa].fa); } if(str[0]=='I') rev1(x),pushup(s[x].fa),pushup(s[s[x].fa].fa); if(str[0]=='S') rev2(x),pushup(s[x].fa),pushup(s[s[x].fa].fa); if(str[0]=='Q') printf("%d ",((s[x].f[0][1]+1)>>1)+((s[x].f[1][0]+1)>>1)); } return 0; }//4 5 (((( Replace 1 2 ) Query 1 2 Swap 2 3 Invert 3 4 Query 1 4 //6 3 )(())( Q 1 6 Q 1 4 Q 3 4