zoukankan      html  css  js  c++  java
  • 【BZOJ2329】括号修复(Splay)

    【BZOJ2329】括号修复(Splay)

    题面

    BZOJ
    洛谷

    题解

    本来想着用线段树来写
    但是有一个区间翻转
    所以不能用线段树了,就只能用平衡树
    然后直接(Splay)就好了
    注意一下几个标记的下放问题
    这种数据结构真的没有什么思路可言。。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define ll long long
    #define RG register
    #define MAX 111111
    #define ls (t[x].ch[0])
    #define rs (t[x].ch[1])
    inline int read()
    {
        RG int x=0,t=1;RG char ch=getchar();
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        if(ch=='-')t=-1,ch=getchar();
        while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
        return x*t;
    }
    struct Node
    {
    	int ch[2],ff,size;
    	int lm,rm,lg,rg,sum,v;
    	int rev,eql,inv;
    }t[MAX];
    int rt;
    void pushup(int x)
    {
    	t[x].lm=max(t[ls].lm,t[ls].sum+t[x].v+t[rs].lm);
    	t[x].rm=max(t[rs].rm,t[rs].sum+t[x].v+t[ls].rm);
    	t[x].lg=min(t[ls].lg,t[ls].sum+t[x].v+t[rs].lg);
    	t[x].rg=min(t[rs].rg,t[rs].sum+t[x].v+t[ls].rg);
    	t[x].sum=t[ls].sum+t[rs].sum+t[x].v;
    	t[x].size=t[ls].size+t[rs].size+1;
    }
    void rotate(int x)
    {
    	int y=t[x].ff,z=t[y].ff;
    	int k=t[y].ch[1]==x;
    	if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
    	t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
    	t[x].ch[k^1]=y;t[y].ff=x;
    	pushup(y);
    }
    void putrev(int x)
    {
    	if(!x)return;
    	swap(t[x].lg,t[x].rg);
    	swap(t[x].lm,t[x].rm);
    	swap(ls,rs);t[x].rev^=1;
    }
    void putinv(int x)
    {
    	if(!x)return;
    	t[x].v*=-1;t[x].inv^=1;t[x].sum*=-1;
    	swap(t[x].lm,t[x].lg);swap(t[x].rm,t[x].rg);
    	t[x].lm*=-1;t[x].lg*=-1;t[x].rm*=-1;t[x].rg*=-1;
    }
    void puteql(int x,int w)
    {
    	if(!x)return;
    	t[x].eql=t[x].v=w;t[x].sum=t[x].size*w;
    	t[x].rev=t[x].inv=0;
    	t[x].lm=t[x].rm=max(0,t[x].sum);
    	t[x].lg=t[x].rg=min(0,t[x].sum);
    }
    void pushdown(int x)
    {
    	if(t[x].eql)puteql(ls,t[x].eql),puteql(rs,t[x].eql),t[x].eql=0;
    	if(t[x].rev)putrev(ls),putrev(rs),t[x].rev^=1;
    	if(t[x].inv)putinv(ls),putinv(rs),t[x].inv^=1;
    }
    void Splay(int x,int goal)
    {
    	while(t[x].ff!=goal)
    	{
    		int y=t[x].ff,z=t[y].ff;
    		if(z!=goal)
    			(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
    		rotate(x);
    	}
    	if(!goal)rt=x;pushup(x);
    }
    int Kth(int x,int k)
    {
    	while(233)
    	{
    		pushdown(x);
    		if(k<=t[ls].size)x=ls;
    		else if(k==t[ls].size+1)return x;
    		else k-=t[ls].size+1,x=rs;
    	}
    }
    int split(int l,int r)
    {
    	int x=Kth(rt,l);Splay(x,0);
    	int y=Kth(rt,r+2);Splay(y,x);
    	return t[y].ch[0];
    }
    void Build(int l,int r,int ff)
    {
    	if(l>r)return;
    	int mid=(l+r)>>1;
    	t[mid].ff=ff;
    	if(ff)t[ff].ch[ff<mid]=mid;
    	else rt=mid;
    	Build(l,mid-1,mid);Build(mid+1,r,mid);
    	pushup(mid);
    }
    char S[MAX];
    int n,m;
    int main()
    {
    	n=read();m=read();
    	scanf("%s",S+1);
    	for(int i=1;i<=n;++i)t[i+1].v=(S[i]=='('?-1:1);
    	Build(1,n+2,0);
    	char ch[10];
    	while(m--)
    	{
    		scanf("%s",ch);
    		int l=read(),r=read(),x=split(l,r);
    		if(ch[0]=='Q')printf("%d
    ",(t[x].lm+1)/2+(1-t[x].rg)/2);
    		else if(ch[0]=='S')putrev(x);
    		else if(ch[0]=='R')
    		{
    			scanf("%s",ch);int w=(ch[0]=='('?-1:1);
    			puteql(x,w);
    		}
    		else putinv(x);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    go_接口
    go_封装
    go_结构体和方法
    go_字符和字符串处理
    go_Map
    为啥别人运行程序那么快,而你的却是龟速?
    大一新生开发的小工具火了!不一样的Python编程体验,现在的新生都这么厉害的吗
    十七种方法轻松解决PyTorch训练速度慢!
    Leetcode 1577 数的平方等于两数乘积的方法数
    C++11的decltype关键字
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8809958.html
Copyright © 2011-2022 走看看