您的位置:首页 > 其它

bzoj 2329 [HNOI2011]括号修复 splay

2016-12-29 09:15 441 查看
区间赋值,区间翻转,区间反转,也就splay能干这些事吧。。。

维护一个区间最小值low,区间最大值up,区间和sum,然后一段区间的答案是

(−low[x]+1)/2+(sum[x]+(−low[x]+1)/2∗2)/2

再打一坨标记就行了,注意标记重叠

#include <bits/stdc++.h>
using namespace std;
#define N 110000
#define which(x) (ch[fa[x]][1]==x)
int n,m,root,cnt;
char s
;
int val
,size
,rev
,inv
,rep
;
int ch
[2],fa
,up
,low
,sum
;
void pushup(int x)
{
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
up[x]=max(up[ch[x][0]],up[ch[x][1]]+sum[ch[x][0]]+val[x]);
low[x]=min(low[ch[x][0]],low[ch[x][1]]+sum[ch[x][0]]+val[x]);
}
void invert(int x)
{
val[x]=-val[x],inv[x]^=1;
sum[x]=-sum[x];
swap(low[x],up[x]);
up[x]=-up[x];low[x]=-low[x];
}
void replace(int x,int v)
{
inv[x]=0;
if(v==1)
{
rep[x]=val[x]=1;sum[x]=size[x];
up[x]=size[x];low[x]=0;
}
else
{
rep[x]=val[x]=-1;sum[x]=-size[x];
up[x]=0;low[x]=-size[x];
}
}
void reverse(int x)
{
rev[x]^=1;
swap(low[x],up[x]);
up[x]=sum[x]-up[x];
low[x]=sum[x]-low[x];
}
void pushdown(int x)
{
if(rev[x])
{
swap(ch[x][0],ch[x][1]);
reverse(ch[x][0]);reverse(ch[x][1]);
rev[x]=0;
}
if(rep[x])
{
replace(ch[x][0],rep[x]);
replace(ch[x][1],rep[x]);
rep[x]=0;
}
if(inv[x])
{
invert(ch[x][0]);invert(ch[x][1]);
inv[x]=0;
}
}
void down(int x)
{
if(fa[x])down(fa[x]);
pushdown(x);
}
int build(int l,int r)
{
if(l>r)return 0;
int mid=(l+r)>>1,ret=++cnt;
val[ret]=(s[mid]=='(' ? 1:-1);
ch[ret][0]=build(l,mid-1);
ch[ret][1]=build(mid+1,r);
fa[ch[ret][0]]=fa[ch[ret][1]]=ret;
pushup(ret);
return ret;
}
int find(int x,int K)
{
pushdown(x);
if(K==size[ch[x][0]]+1)return x;
if(K<=size[ch[x][0]])
return find(ch[x][0],K);
return find(ch[x][1],K-size[ch[x][0]]-1);
}
void rotate(int x)
{
int y=fa[x],k=which(x);
ch[y][k]=ch[x][k^1];
ch[x][k^1]=y;
ch[fa[y]][which(y)]=x;

fa[x]=fa[y];fa[y]=x;
fa[ch[y][k]]=y;
pushup(y);pushup(x);
}
void splay(int x,int tar)
{
down(x);
while(fa[x]!=tar)
{
int y=fa[x];
if(fa[y]==tar)rotate(x);
else
{
if(which(x)^which(y))rotate(x);
else rotate(y);
rotate(x);
}
}
if(!tar)root=x;
}
int main()
{
scanf("%d%d%s",&n,&m,s+1);
root=build(0,n+1);
for(int l,r;m--;)
{
scanf("%s%d%d",s+1,&l,&r);
int pl=find(root,l),pr=find(root,r+2);
splay(pl,0);splay(pr,root);
int x=ch[pr][0];
if(s[1]=='R')
{
scanf("%s",s+1);
replace(x,s[1]=='(' ? 1:-1);
}
else if(s[1]=='S')reverse(x);
else if(s[1]=='I')invert(x);
else
{
int t=(-low[x]+1)/2;
printf("%d\n",t+(sum[x]+t*2)/2);
}
pushup(pr);pushup(pl);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: