zoukankan      html  css  js  c++  java
  • 【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} floor + lfloor frac{Num{(}+1}{2} floor$。

    然后只需要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
    ",SplayTree::Query(l,r)); break;
    			case 'S' : SplayTree::Rever(l,r); break;
    			case 'I' : SplayTree::Inver(l,r); break;
    		} 
    	}
    	
    	return 0;
    }
    

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

  • 相关阅读:
    luogu 2742 二维凸包
    poj2398 Toy Storage 计算几何,叉积,二分
    luoguP1742 最小圆覆盖
    bzoj4501 旅行
    cf1173 D. Nauuo and Circle
    bzoj3745: [Coci2015]Norma 分治,单调队列
    bzoj1176: [Balkan2007]Mokia cdq
    luoguP3964 [TJOI2013]松鼠聚会
    浅谈数学期望
    tarjan模板(带注释)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/6358454.html
Copyright © 2011-2022 走看看