zoukankan      html  css  js  c++  java
  • 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay

    【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列

    题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作,还要维护左边有多少多余的左括号,右边有多少多余的右括号(如果一个右括号匹配一个左括号的话)。然后xjb维护一番即可。。。

    答案是什么呢?$lceil{左边多余的右括号数over 2} ceil+lceil{右边多余的左括号数over 2} ceil$。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=100010;
    int n,m,rt;
    struct node
    {
    	int v,f[2][2],ch[2],fa,siz,tag;
    	bool r1,r2;
    }s[maxn];
    char str[maxn];
    //'('->0 ')'->1 r1->反 r2->翻
    inline int ab(const int &a) {return a>0?a:0;}
    inline void pushup(int x)
    {
    	int l=s[x].ch[0],r=s[x].ch[1];
    	s[x].siz=s[l].siz+s[r].siz+1;
    	s[x].f[0][0]=s[l].f[0][0]+ab(s[r].f[0][0]-s[x].v-s[l].f[1][1]);
    	s[x].f[1][1]=s[r].f[1][1]+ab(s[l].f[1][1]+s[x].v-s[r].f[0][0]);
    	s[x].f[0][1]=s[l].f[0][1]+ab(s[r].f[0][1]+s[x].v-s[l].f[1][0]);
    	s[x].f[1][0]=s[r].f[1][0]+ab(s[l].f[1][0]-s[x].v-s[r].f[0][1]);
    }
    inline void rev1(int x)
    {
    	s[x].tag=-s[x].tag,s[x].v=-s[x].v,s[x].r1^=1,swap(s[x].f[0][0],s[x].f[0][1]),swap(s[x].f[1][0],s[x].f[1][1]);
    }
    inline void rev2(int x)
    {
    	s[x].r2^=1,swap(s[x].ch[0],s[x].ch[1]),swap(s[x].f[0][0],s[x].f[1][0]),swap(s[x].f[0][1],s[x].f[1][1]);
    }
    inline void cover(int x,int y)
    {
    	s[x].tag=s[x].v=y,s[x].f[0][y>0]=s[x].f[1][y>0]=s[x].siz,s[x].f[0][y<0]=s[x].f[1][y<0]=0,s[x].r1=s[x].r2=0;
    }
    inline void pushdown(int x)
    {
    	int l=s[x].ch[0],r=s[x].ch[1];
    	if(s[x].tag)
    	{
    		if(l)	cover(l,s[x].tag);
    		if(r)	cover(r,s[x].tag);
    		s[x].tag=0;
    	}
    	if(s[x].r1)
    	{
    		if(l)	rev1(l);
    		if(r)	rev1(r);
    		s[x].r1=0;
    	}
    	if(s[x].r2)
    	{
    		if(l)	rev2(l);
    		if(r)	rev2(r);
    		s[x].r2=0;
    	}
    }
    inline void rotate(int x,int &k)
    {
    	int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]);
    	if(y!=k)	s[z].ch[y==s[z].ch[1]]=x;
    	else	k=x;
    	s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1];
    	if(s[x].ch[d^1])	s[s[x].ch[d^1]].fa=y;
    	s[x].ch[d^1]=y;
    	pushup(y),pushup(x);
    }
    inline void splay(int x,int &k)
    {
    	while(x!=k)
    	{
    		int y=s[x].fa,z=s[y].fa;
    		if(y!=k)
    		{
    			if((x==s[y].ch[0])^(y==s[z].ch[0]))	rotate(x,k);
    			else	rotate(y,k);
    		}
    		rotate(x,k);
    	}
    }
    int find(int x,int y)
    {
    	if(!x)	return 0;
    	pushdown(x);
    	if(s[s[x].ch[0]].siz>=y)	return find(s[x].ch[0],y);
    	if(s[s[x].ch[0]].siz+1<y)	return find(s[x].ch[1],y-s[s[x].ch[0]].siz-1);
    	return x;
    }
    inline void split(int a,int b)
    {
    	splay(find(rt,a),rt),splay(find(rt,b+2),s[rt].ch[1]);
    }
    int build(int l,int r)
    {
    	if(l>r)	return 0;
    	int x=(l+r)>>1;
    	s[x].ch[0]=build(l,x-1),s[x].ch[1]=build(x+1,r);
    	if(s[x].ch[0])	s[s[x].ch[0]].fa=x;
    	if(s[x].ch[1])	s[s[x].ch[1]].fa=x;
    	pushup(x);
    	return x;
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	//freopen("bz2329.in","r",stdin);
    	n=rd(),m=rd();
    	int i,a,b,x;
    	scanf("%s",str+1);
    	for(i=1;i<=n;i++)	s[i+1].v=(str[i]=='(')?-1:1;
    	rt=build(1,n+2);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%s",str),a=rd(),b=rd(),split(a,b),x=s[s[rt].ch[1]].ch[0];
    		if(str[0]=='R')
    		{
    			scanf("%s",str);
    			cover(x,(str[0]=='(')?-1:1),pushup(s[x].fa),pushup(s[s[x].fa].fa);
    		}
    		if(str[0]=='I')	rev1(x),pushup(s[x].fa),pushup(s[s[x].fa].fa);
    		if(str[0]=='S')	rev2(x),pushup(s[x].fa),pushup(s[s[x].fa].fa);
    		if(str[0]=='Q')	printf("%d
    ",((s[x].f[0][1]+1)>>1)+((s[x].f[1][0]+1)>>1));
    	}
    	return 0;
    }//4 5 (((( Replace 1 2 ) Query 1 2 Swap 2 3 Invert 3 4 Query 1 4
    //6 3 )(())( Q 1 6 Q 1 4 Q 3 4 
  • 相关阅读:
    javascript之数组去重方法
    经典问题之爬楼梯
    javascript之事件循环机制
    javascript之闭包
    javascript之动态改变this上下文
    块级元素的垂直居中对齐
    js数组对象
    javascript-冒泡法排序
    javascript-数组
    javascript-循环
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7954606.html
Copyright © 2011-2022 走看看