BZOJ2329: [HNOI2011]括号修复

用1表示左括号,-1表示右括号,lmin表示从左开始的最小连续和,rmax表示从右开始的最大连续和,答案为(1-lmin)/2+(1+rmax)/2,splay维护即可。

#include<algorithm>
#include<cstdio>
#define Z(o)(o->i->s1+1)
#define M (i+j>>1)
using namespace std;
const int N=1e5+5;
typedef struct node*ptr;
struct node{
	ptr i,j;
	int v,t1,t2,t3,s1,s2,s3,s4,s5,s6;
	ptr up(){
		i->down(),j->down();
		s1=i->s1+1+j->s1;
		s2=i->s2+v+j->s2;
		s3=min(i->s3,i->s2+v+j->s3);
		s4=max(i->s4,i->s2+v+j->s4);
		s5=min(j->s5,j->s2+v+i->s5);
		s6=max(j->s6,j->s2+v+i->s6);
		return this;
	}
	ptr down();
}e[N];
ptr node::down(){
	if(this==e)return e;
	if(t1){
		i->t1=j->t1=v=t1,s2=s1*t1;
		if(t1>0)
			s3=s5=0,s4=s6=s2;
		else
			s4=s6=0,s3=s5=s2;
		t1=t2=t3=0;
	}
	if(t2&&t2--){
		i->t2^=1,j->t2^=1;
		swap(i,j);
		swap(s3,s5);
		swap(s4,s6);
	}
	if(t3&&t3--){
		i->t3^=1,i->t1*=-1;
		j->t3^=1,j->t1*=-1;
		v*=-1,s2*=-1;
		swap(s3*=-1,s4*=-1);
		swap(s5*=-1,s6*=-1);
	}
	return this;
}
ptr a=e;
ptr pre(char*z,int i,int j){
	if(i>j)return e;
	node s={pre(z,i,M-1),pre(z,M+1,j),z[M]=='('?1:-1};
	return(*++a=s).up();
}
void zig(ptr&o,ptr&s){ptr t=o->i;o->i=s,s=o->up(),o=t;}
void zag(ptr&o,ptr&s){ptr t=o->j;o->j=s,s=o->up(),o=t;}
ptr splay(int v,ptr&o){
	ptr s=e,t=e;
	while(v!=Z(o->down()))
		if(v<Z(o)){
			if(v<Z(o->i->down()))
				zig(o,o->i->j);
			zig(o,s);
		}else{
			v-=Z(o);
			if(v>Z(o->j->down()))
				v-=Z(o->j),zag(o,o->j->i);
			zag(o,t);
		}
	while(s!=e)zig(s,o->j);
	while(t!=e)zag(t,o->i);
	return o->up();
}
ptr&splay(int s,int t,ptr&r){
	splay(s,r);
	return splay(t-s+2,r->j)->i;
}
int main(){
	int n,m,s,t;
	static char c,f[N],z[N];
	scanf("%d%d%s",&n,&m,f+1);
	ptr r=pre(f,0,n+1);
	while(m--){
		scanf("%s%d%d",z,&s,&t);
		ptr o=splay(s,t,r);
		if(*z=='R')
			scanf(" %c",&c),o->t1=c=='('?1:-1;
		if(*z=='S')o->t2=1;
		if(*z=='I')o->t3=1;
		if(*z=='Q')
			printf("%d\n",(1-o->s3)/2+(1+o->s6)/2);
	}
}
posted @ 2016-05-15 20:30  f321dd  阅读(160)  评论(0编辑  收藏  举报