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;
}

浙公网安备 33010602011771号