首页 > 代码库 > BZOJ2209: [Jsoi2011]括号序列

BZOJ2209: [Jsoi2011]括号序列

传送门

splay练习。

考虑把括号序列转化成类似于区间最大/最小值的情况。

显然我们可以知道括号序列消完的情况肯定是$a$个)和$b$个(,那么把这些括号全部合法化的代价显然就是$\frac{a+1}{2}+\frac{b+1}{2}$。

接着我们可以把‘(‘变为1,把‘)‘变为-1,然后每次取左区间的连续最小值,右区间的连续最大值,就是$a$与$b$的大小。

因为存在区间翻转,所以需要把左/右区间的连续最大/小值都搞出来。

splay即可。

//BZOJ2209//by Cydiater//2017.2.15#include <iostream>#include <iomanip>#include <cstring>#include <string>#include <queue>#include <map>#include <cmath>#include <ctime>#include <cstdlib>#include <cstdio>#include <algorithm>#include <bitset>#include <set>#include <vector>#include <complex>using namespace std;#define ll long long#define up(i,j,n)	for(int i=j;i<=n;i++)#define down(i,j,n)	for(int i=j;i>=n;i--)#define cmax(a,b)	a=max(a,b)#define cmin(a,b)	a=min(a,b)const int MAXN=1e5+5;const int oo=0x3f3f3f3f;inline int read(){	char ch=getchar();int x=0,f=1;	while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}	return x*f;}int root,cnt=0,N,M,arr[MAXN];char s[MAXN];struct SplayTree{	int son[2],l0,l1,r0,r1,sum,fa,siz,tag0,tag1,val;}t[MAXN];namespace solution{	inline int get(int k){return t[t[k].fa].son[1]==k;}	inline void reload(int k){		int s1=t[k].son[0],s2=t[k].son[1];		t[k].l0=min(t[s1].l0,t[s1].sum+t[k].val+t[s2].l0);		t[k].l1=max(t[s1].l1,t[s1].sum+t[k].val+t[s2].l1);		t[k].r0=min(t[s2].r0,t[s2].sum+t[k].val+t[s1].r0);		t[k].r1=max(t[s2].r1,t[s2].sum+t[k].val+t[s1].r1);		t[k].siz=t[s1].siz+t[s2].siz+1;		t[k].sum=t[s1].sum+t[s2].sum+t[k].val;			}	inline void push0(int k){		if(!k)return;		swap(t[k].l0,t[k].l1);t[k].l0*=-1;t[k].l1*=-1;		swap(t[k].r0,t[k].r1);t[k].r0*=-1;t[k].r1*=-1;		t[k].tag0^=1;t[k].val*=-1;t[k].sum*=-1;	}	inline void push1(int k){		if(!k)return;		swap(t[k].l0,t[k].r0);		swap(t[k].l1,t[k].r1);		t[k].tag1^=1;	}	inline void Pushdown(int k){		int s1=t[k].son[0],s2=t[k].son[1];		if(t[k].tag1){			push1(s1);push1(s2);			swap(t[k].son[0],t[k].son[1]);			t[k].tag1=0;		}		if(t[k].tag0){			push0(s1);push0(s2);			t[k].tag0=0;		}	}	inline void rotate(int k){		int old=t[k].fa,oldf=t[old].fa,which=get(k);		t[old].son[which]=t[k].son[which^1];t[t[old].son[which]].fa=old;		t[k].son[which^1]=old;t[old].fa=k;		t[k].fa=oldf;		if(oldf)t[oldf].son[t[oldf].son[1]==old]=k;		reload(old);reload(k);	}	inline void splay(int k,int aim){		for(int fa;(fa=t[k].fa);rotate(k)){			if(k==aim)break;			else if(fa==aim){				rotate(k);				break;			}else if(t[fa].fa==aim){				rotate(get(fa)==get(k)?fa:k);				rotate(k);				break;			}else rotate(get(fa)==get(k)?fa:k);		}		if(aim==root)root=k;	}	int Node(int rnk){		int now=root;		while(true){			Pushdown(now);			int lsiz=t[now].son[0]?t[t[now].son[0]].siz:0;			if(rnk<=lsiz)now=t[now].son[0];			else{				if(rnk==lsiz+1)return now;				rnk-=lsiz+1;				now=t[now].son[1];			}		}	}	int Match(int L,int R){		int kl=Node(L),kr=Node(R+2);		splay(kl,root);splay(kr,t[root].son[1]);		return kr;	}	void Build(int L,int R,int &k,int fa){		if(!k)k=++cnt;		int mid=(L+R)>>1;		t[k].fa=fa;t[k].siz=1;t[k].tag0=t[k].tag1=0;		t[k].l0=t[k].l1=t[k].r0=t[k].r1=0;t[k].val=arr[mid];		if(L==R){			t[k].son[0]=t[k].son[1]=0;			t[k].sum=t[k].val;			t[k].l0=t[k].l1=t[k].r0=t[k].r1=t[k].val;			cmin(t[k].l0,0);cmin(t[k].r0,0);			cmax(t[k].l1,0);cmax(t[k].r1,0);			return;		}		if(L<=mid-1)Build(L,mid-1,t[k].son[0],k);		if(mid+1<=R)Build(mid+1,R,t[k].son[1],k);		reload(k);	}	int Col(int L,int R){		int k=Match(L,R);		return ((t[t[k].son[0]].r1+1)/2)-((t[t[k].son[0]].l0-1)/2);	}	void Inv(int L,int R){		int k=Match(L,R);		push0(t[k].son[0]);		reload(k);reload(t[k].fa);	}	void Rev(int L,int R){		int k=Match(L,R);		push1(t[k].son[0]);		reload(k);reload(t[k].fa);	}	void Prepare(){		N=read();M=read();		scanf("%s",s+1);		up(i,1,N)arr[i]=(s[i]==‘(‘?1:-1);		arr[0]=0;arr[N+1]=0;		Build(0,N+1,root,0);	}	void Solve(){		//DEBUG(root);		while(M--){			int op=read(),L=read(),R=read();			if(op==0)printf("%d\n",Col(L,R));			if(op==1)Inv(L,R);			if(op==2)Rev(L,R);		}	}}int main(){	using namespace solution;	Prepare();	Solve();	return 0;}

 

BZOJ2209: [Jsoi2011]括号序列