UOJ#31. 【UR #2】猪猪侠再战括号序列 splay
显然可以直接凑左面全是左括号,右面全是右括号的情况.
然后区间翻转就用 splay 模拟好了.
splay 的时候一定注意一点:
如果没有调用 find(x),就一定要手动把 x 及其祖先的节点 pushdown.
code;
#include <bits/stdc++.h> #define N 100009 #define ll long long #define lson s[x].ch[0] #define rson s[x].ch[1] #define setIO(s) freopen(s".in","r",stdin) using namespace std; char str[N<<1]; int n,tot,root,A[N<<1],sta[N<<1]; struct node { int ch[2],rev,f,w,pos,si; }s[N<<1]; int get(int x) { return s[s[x].f].ch[1]==x; } void mark(int x) { swap(lson,rson),s[x].rev^=1; } void pushup(int x) { int l=lson,r=rson; s[x].si=s[l].si+s[r].si+1; if(s[x].w==1) s[x].pos=x; else s[x].pos=0; if(s[l].pos) s[x].pos=s[l].pos; if(s[r].pos) s[x].pos=s[r].pos; } void pushdown(int x) { if(s[x].rev) { if(lson) mark(lson); if(rson) mark(rson); s[x].rev=0; } } void rotate(int x) { int old=s[x].f,fold=s[old].f,which=get(x); s[old].ch[which]=s[x].ch[which^1]; if(s[old].ch[which]) s[s[old].ch[which]].f=old; s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold; if(fold) s[fold].ch[s[fold].ch[1]==old]=x; pushup(old),pushup(x); } void splay(int x,int &tar) { int fa,u=x,v=0; for(sta[++v]=u;u!=tar;u=s[u].f) sta[++v]=s[u].f; for(;v;--v) pushdown(sta[v]); for(u=s[u].f;(fa=s[x].f)!=u;rotate(x)) if(s[fa].f!=u) rotate(get(fa)==get(x)?fa:x); tar=x; } int find(int x,int kth) { pushdown(x); if(s[lson].si+1==kth) return x; else { if(s[lson].si>=kth) return find(lson,kth); else return find(rson,kth-s[lson].si-1); } } int build(int l,int r,int ff) { int mid=(l+r)>>1; int cur=++tot; s[cur].f=ff; s[cur].w=A[mid]; if(mid>l) s[cur].ch[0]=build(l,mid-1,cur); if(r>mid) s[cur].ch[1]=build(mid+1,r,cur); pushup(cur); return cur; } int cnt; int tl[N],tr[N]; int main() { // setIO("input"); scanf("%s",str+1),n=strlen(str+1); for(int i=1;i<=n;++i) A[i]=(str[i]=='('?1:-1); root=build(0,n+1,0); for(int i=1;i<=n/2;++i) { int CUR; splay(CUR=find(root,i+1),root); if(s[root].w==1) continue; else{ int PRE=find(root,i); splay(PRE,root); int z=s[s[PRE].ch[1]].pos; splay(z,root); int k=s[s[z].ch[0]].si+1; splay(PRE,root); splay(find(root,k+1),s[PRE].ch[1]); int tmp=s[s[PRE].ch[1]].ch[0]; mark(tmp); ++cnt; tl[cnt]=i,tr[cnt]=k-1; } } printf("%d\n",cnt); for(int i=1;i<=cnt;++i) printf("%d %d\n",tl[i],tr[i]); return 0; }