标签:
神题。
用-1表示左括号,1表示右括号,lmax表示从左开始的最大连续和,rmin表示从右开始的最小连续和,答案为(lmax+1)/2+(-rmin+1)/2。
Splay维护即可。
#include<bits/stdc++.h>
#define L(t) (t)->c[0]
#define R(t) (t)->c[1]
#define Z(t) (L(t)->s+1)
#define M (l+r>>1)
using namespace std;
struct node{
int v,s;
int sum,lmin,lmax,rmin,rmax;
int same;
bool flip,rev;
node* c[2];
node(int v,node* a,node* u)
:v(v),sum(v){
lmin=lmax=rmin=rmax
=s=same=flip=rev=0;
c[0]=a,c[1]=u;
}
}*null=new node(0,0,0),*root;
void same(int s,node* t){
t->flip=t->rev=0;
t->sum=t->s*(t->v=t->same=s);
t->lmin=t->rmin=min(t->sum,0);
t->lmax=t->rmax=max(t->sum,0);
}
void flip(node* t){
if(t->same)
return same(t->v*-1,t);
t->flip^=1;
t->v*=-1,t->sum*=-1;
swap(t->lmin*=-1,t->lmax*=-1);
swap(t->rmin*=-1,t->rmax*=-1);
}
void rev(node* t){
if(t->same)
return;
t->rev^=1;
swap(L(t),R(t));
swap(t->lmin,t->rmin);
swap(t->lmax,t->rmax);
}
void devolve(node* t){
if(t==null)
return;
for(int i=0;i!=2;++i){
if(t->same)
same(t->v,t->c[i]);
if(t->flip)
flip(t->c[i]);
if(t->rev)
rev(t->c[i]);
}
t->same=t->flip=t->rev=0;
}
node* update(node* t){
devolve(L(t));
devolve(R(t));
t->s=R(t)->s+Z(t);
t->sum=L(t)->sum+t->v+R(t)->sum;
t->lmin=min(L(t)->lmin,
L(t)->sum+t->v+R(t)->lmin);
t->lmax=max(L(t)->lmax,
L(t)->sum+t->v+R(t)->lmax);
t->rmin=min(R(t)->rmin,
R(t)->sum+t->v+L(t)->rmin);
t->rmax=max(R(t)->rmax,
R(t)->sum+t->v+L(t)->rmax);
return t;
}
void link(bool i,node*& t,node*& s){
node* d=t->c[i];
t->c[i]=s;
s=update(t);
t=d;
}
void splay(int v,node*& t=root){
node* d[]={null,null};
while(1){
devolve(t);
if(v==Z(t))
break;
bool i=v>Z(t);
v-=i*Z(t);
devolve(t->c[i]);
if(v!=Z(t->c[i])
&&i==v>Z(t->c[i])){
v-=i*Z(t->c[i]);
link(i,t,t->c[i]->c[i^1]);
}
link(i,t,d[i]);
}
for(int i=0;i!=2;++i){
node* s=t->c[i^1];
while(d[i]!=null)
link(i,d[i],s);
t->c[i^1]=s;
}
update(t);
}
node* build(char* v,int l,int r){
return l>r?null
:update(new node(
v[M]^‘(‘?1:-1,
build(v,l,M-1),
build(v,M+1,r)));
}
node*& interval(int l,int r){
splay(l);
splay(r-l+2,R(root));
return L(R(root));
}
char s[100010];
int main(){
int n,m,u,v;
scanf("%d%d%s",&n,&m,s+1);
root=build(s,0,n+1);
while(m--){
char t[8],a[2];
scanf("%s%d%d",t,&u,&v);
if(*t==‘R‘){
scanf("%s",a);
same(*a^‘(‘?1:-1,
interval(u,v));
}
if(*t==‘S‘)
rev(interval(u,v));
if(*t==‘I‘)
flip(interval(u,v));
if(*t==‘Q‘){
node* t=interval(u,v);
printf("%d\n",(t->lmax
+1)/2+(-t->rmin+1)/2);
}
}
}
bzoj2329: [HNOI2011]括号修复 Splay
标签:
原文地址:http://www.cnblogs.com/f321dd/p/5496015.html