题链:
Splay
类似 BZOJ 2329 [HNOI2011]括号修复
只是多了一个Replace(替换)操作,
然后就要主要lazy标记之间的影响了。
1).Replace可以直接覆盖另外两个标记,
2).当已经有Replace标记,再覆盖Invert标记时,直接把Replace标记取反即可;在覆盖Swap标记时,Replace标记不变。
代码:
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 100500 using namespace std; char s[10]; int N,M; struct SPT{ int pmx[MAXN],pmn[MAXN],smx[MAXN],smn[MAXN],sum[MAXN],key[MAXN]; int ch[MAXN][2],siz[MAXN],fa[MAXN],cg[MAXN],lazy[MAXN],rt; void Invert(int x){ sum[x]*=-1; key[x]*=-1; pmx[x]*=-1; pmn[x]*=-1; swap(pmx[x],pmn[x]); smx[x]*=-1; smn[x]*=-1; swap(smx[x],smn[x]); } void Swap(int x){ swap(pmx[x],smx[x]); swap(pmn[x],smn[x]); swap(ch[x][0],ch[x][1]); } void Replace(int x,int c){ key[x]=c; sum[x]=c*siz[x]; pmx[x]=max(sum[x],0); pmn[x]=min(sum[x],0); smx[x]=max(sum[x],0); smn[x]=min(sum[x],0); } void Pushup(int x){ siz[x]=siz[ch[x][0]]+1+siz[ch[x][1]]; sum[x]=sum[ch[x][0]]+key[x]+sum[ch[x][1]]; pmx[x]=max(pmx[ch[x][0]],sum[ch[x][0]]+key[x]+pmx[ch[x][1]]); pmn[x]=min(pmn[ch[x][0]],sum[ch[x][0]]+key[x]+pmn[ch[x][1]]); smx[x]=max(smx[ch[x][1]],sum[ch[x][1]]+key[x]+smx[ch[x][0]]); smn[x]=min(smn[ch[x][1]],sum[ch[x][1]]+key[x]+smn[ch[x][0]]); } void Pushdown(int x){ if(cg[x]!=0){ Replace(ch[x][0],cg[x]); cg[ch[x][0]]=cg[x]; lazy[ch[x][0]]=0; Replace(ch[x][1],cg[x]); cg[ch[x][1]]=cg[x]; lazy[ch[x][1]]=0; cg[x]=0; } if(lazy[x]&1){ Invert(ch[x][0]); if(!cg[ch[x][0]]) lazy[ch[x][0]]^=1; else cg[ch[x][0]]*=-1; Invert(ch[x][1]); if(!cg[ch[x][1]]) lazy[ch[x][1]]^=1; else cg[ch[x][1]]*=-1; lazy[x]^=1; } if(lazy[x]&2){ Swap(ch[x][0]); if(!cg[ch[x][0]]) lazy[ch[x][0]]^=2; Swap(ch[x][1]); if(!cg[ch[x][1]]) lazy[ch[x][1]]^=2; lazy[x]^=2; } } void Rotate(int x,int &k){ static int y,z,l,r; y=fa[x]; z=fa[y]; l=ch[y][0]!=x; r=l^1; if(!z) k=x; else ch[z][ch[z][0]!=y]=x; fa[ch[x][r]]=y; fa[y]=x; fa[x]=z; ch[y][l]=ch[x][r]; ch[x][r]=y; Pushup(y); } void Splay(int x,int &k){ static int y,z; while(x!=k){ y=fa[x]; z=fa[y]; if(y!=k) (ch[z][0]!=y)^(ch[y][0]!=x)? Rotate(x,k):Rotate(y,k); Rotate(x,k); } Pushup(x); } int find(int x,int num){ Pushdown(x); if(num<=siz[ch[x][0]]) return find(ch[x][0],num); else if(num==siz[ch[x][0]]+1) return x; else return find(ch[x][1],num-siz[ch[x][0]]-1); } int Split(int l,int r){ static int dl,dr; dl=find(rt,l); dr=find(rt,r+2); Splay(dl,rt); Splay(dr,ch[dl][1]); return ch[dr][0]; } void Modify(int l,int r,int type){ static int p; p=Split(l,r); if(type==3){ Replace(p,(s[0]==‘(‘?1:-1)); cg[p]=(s[0]==‘(‘?1:-1); lazy[p]=0; } else{ if(type==1) Invert(p); else Swap(p); if(!cg[p]) lazy[p]^=type; else if(type==1) cg[p]*=-1; } Pushup(fa[p]); Pushup(fa[fa[p]]); } void Build(int &x,int dad,int l,int r){ static char c; if(l>r) return; x=(l+r)>>1; fa[x]=dad; Build(ch[x][0],x,l,x-1); scanf(" %c",&c); key[x]=(c==‘(‘?1:-1); Build(ch[x][1],x,x+1,r); Pushup(x); } void BorderBuild(){ rt=N+1; key[N+1]=0; key[N+2]=0; ch[N+1][1]=N+2; fa[N+2]=N+1; Build(ch[N+2][0],N+2,1,N); Pushup(N+2); Pushup(N+1); } int Query(int l,int r){ static int p,ANS,nl,nr; p=Split(l,r); nl=-pmn[p]; nr=smx[p]; ANS=(nl+1)/2+(nr+1)/2; return ANS; } }DT; int main(){ freopen("/home/noilinux/Documents/模块学习/2329.in","r",stdin); freopen("/home/noilinux/Documents/模块学习/2329.out","w",stdout); scanf("%d%d",&N,&M); DT.BorderBuild(); for(int i=1,l,r;i<=M;i++){ scanf("%s",s); scanf("%d%d",&l,&r); if(s[0]==‘Q‘) printf("%d\n",DT.Query(l,r)); if(s[0]==‘I‘) DT.Modify(l,r,1); if(s[0]==‘S‘) DT.Modify(l,r,2); if(s[0]==‘R‘) scanf("%s",s),DT.Modify(l,r,3); } return 0; }