【BZOJ-2329&2209】括号修复&括号序列 Splay

2329: [HNOI2011]括号修复

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 1007  Solved: 476
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

Sample Output

HINT

Source

Solution

一眼Splay么....关键是怎么维护...

一开始看错题了...想了很久歪路,其实想一下还是可以想到的么..

对于一个括号序列,首先合法的括号对是对询问答案没有贡献的,所以可以忽略,剩余的括号序列必然是形如$)*(*$的序列。

所以答案显然就是$\lfloor \frac{Num_{)}+1}{2} \rfloor + \lfloor \frac{Num{(}+1}{2} \rfloor$。

然后只需要Splay中维护左右起最大连续$($左右起最大连续$)$,即可得到答案。

考虑怎么维护这样的东西..括号序列一种最典型的表示方式可以认为是$+1-1$,这里也一样啊,不妨令$(=-1$,$)=+1$

这样就可以以一种类似最大最小连续子段和的方式去维护上述量了。

然后就是修改操作。

覆盖操作显然会清空翻转操作和取反操作,问题在于取反操作和覆盖操作的下放顺序会对结果有影响!!!(画图考虑一下)

所以值得注意的就是,在下放标记的时候,取反标记同样会使覆盖标记发生取反。(再画图考虑一下)

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
inline int read()
{
	int x=0,f=1; char ch=getchar();
	while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
	while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
	return x*f;
}
#define MAXN 100010
#define INF 0x3fffffff 
int N,M;
char s[MAXN];

namespace SplayTree{
#define lson(x) son[x][0]
#define rson(x) son[x][1]
	int son[MAXN][2],fa[MAXN],root,sz;
	int lmin[MAXN],rmin[MAXN],lmax[MAXN],rmax[MAXN],size[MAXN],sum[MAXN],val[MAXN];
	int rev[MAXN],inv[MAXN],cov[MAXN];
	inline void Newnode(int &x,int last,int v)
	{
		x=++sz;
		size[x]=1; 
		val[x]=sum[x]=v;
		if (v==1)
			lmin[x]=rmin[x]=0,lmax[x]=rmax[x]=v;
		else
			lmin[x]=rmin[x]=v,lmax[x]=rmax[x]=0;
		fa[x]=last; son[x][0]=son[x][1]=0;
	}
	inline int Right(int x) {return son[fa[x]][1]==x;}
	inline void Update(int x)
	{
		if (!x) return;
		sum[x]=sum[lson(x)]+sum[rson(x)]+val[x];
		size[x]=size[lson(x)]+size[rson(x)]+1;
		lmax[x]=max(lmax[lson(x)],sum[lson(x)]+val[x]+lmax[rson(x)]);
		rmax[x]=max(rmax[rson(x)],sum[rson(x)]+val[x]+rmax[lson(x)]);
		lmin[x]=min(lmin[lson(x)],sum[lson(x)]+val[x]+lmin[rson(x)]);
		rmin[x]=min(rmin[rson(x)],sum[rson(x)]+val[x]+rmin[lson(x)]);
	}
	inline void Rev(int x)
	{
		if (!x) return;
		rev[x]^=1;
		swap(son[x][0],son[x][1]);
		swap(lmax[x],rmax[x]),swap(lmin[x],rmin[x]);
	}
	inline void Cov(int x,int d)
	{
		if (!x) return;
		cov[x]=d; rev[x]=0; inv[x]=0;
		sum[x]=d*size[x]; val[x]=d;
		if (d==1)
			lmax[x]=rmax[x]=size[x],lmin[x]=rmin[x]=0;
		else
			lmax[x]=rmax[x]=0,lmin[x]=rmin[x]=-size[x];
	}
	inline void Inv(int x)
	{
		if (!x) return;
		inv[x]^=1;
		sum[x]=-sum[x]; val[x]=-val[x];
		swap(lmax[x],lmin[x]),swap(rmax[x],rmin[x]);
		lmax[x]=-lmax[x],rmax[x]=-rmax[x];
		lmin[x]=-lmin[x],rmin[x]=-rmin[x];
		cov[x]=-cov[x];
	}
	inline void Pushdown(int x)
	{
		if (rev[x]!=0)
			Rev(son[x][0]),Rev(son[x][1]),rev[x]^=1;
		if (inv[x]!=0)
			Inv(son[x][0]),Inv(son[x][1]),inv[x]^=1;
		if (cov[x]!=0)
			Cov(son[x][0],cov[x]),Cov(son[x][1],cov[x]),cov[x]=0;
	}
	inline int Build(int l,int r,int last)
	{
		int mid=(l+r)>>1,x;
		Newnode(x,last,s[mid]=='('? -1:1);
		if (mid-1>=l) son[x][0]=Build(l,mid-1,x);
		if (mid+1<=r) son[x][1]=Build(mid+1,r,x);
		Update(x);
		return x; 
	}
	inline void Rotate(int x)
	{
		int y=fa[x],z=fa[y],w=Right(x);
		Pushdown(y); Pushdown(x);
		son[y][w]=son[x][w^1]; fa[son[y][w]]=y;
		fa[y]=x; son[x][w^1]=y; fa[x]=z;
		if (z) son[z][son[z][1]==y]=x;
		Update(y); Update(x);
	}
	inline void Splay(int x,int tar)
	{
		for (int y; (y=fa[x])!=tar; Rotate(x))
			if (fa[y]!=tar) Rotate(Right(x)==Right(y) ? y:x);
		if (!tar) root=x;
	}
	inline int Find(int x,int k)
	{
		Pushdown(x);
		if (size[son[x][0]]>=k) return Find(son[x][0],k);
		if (size[son[x][0]]+1==k) return x;
		return Find(son[x][1],k-size[son[x][0]]-1);
	}
	inline int Split(int l,int r) 
	{
		int x=Find(root,l),y=Find(root,r+2);
		Splay(x,0); Splay(y,root); return lson(rson(root));
	}
	inline void Cover(int l,int r,int d) {int x=Split(l,r); Cov(x,d);}
	inline void Rever(int l,int r) {int x=Split(l,r); Rev(x);}
	inline void Inver(int l,int r) {int x=Split(l,r); Inv(x);}
	inline int Query(int l,int r) {int x=Split(l,r); return (lmax[x]+1)/2+(-rmin[x]+1)/2;}
}using namespace SplayTree; 

int main()
{
	Newnode(root,0,0);
	Newnode(son[root][1],root,0);
	
	N=read(),M=read();
	scanf("%s",s+1); 
	
	son[son[root][1]][0]=SplayTree::Build(1,N,son[root][1]);
	
	while (M--) {
		char opt[10]; scanf("%s",opt+1);
		int l=read(),r=read();
		switch (opt[1]) {
			case 'R' : scanf("%s",s+1); SplayTree::Cover(l,r,s[1]=='('? -1:1); break;
			case 'Q' : printf("%d\n",SplayTree::Query(l,r)); break;
			case 'S' : SplayTree::Rever(l,r); break;
			case 'I' : SplayTree::Inver(l,r); break;
		} 
	}
	
	return 0;
}

大过年的,写啥Splay啊....这道题又捯饬了两个多小时...真是自虐。

posted @ 2017-01-30 22:34  DaD3zZ  阅读(448)  评论(0编辑  收藏  举报