BZOJ 2329: [HNOI2011]括号修复 Splay

Description

题解:

随便给定一个括号序列,最终一定能表示成 $..)))))))((((...$ 这种形式.

那么,这个时候答案就是左括号数量/2+右括号数量/2(都是向上取整)

所以,我们考虑用 $Splay$ 来维护这种情况下左括号和右括号的数量.

这里的那个 $swap$ 不是镜面翻转,所以在维护的时候要维护一个反串的数量.

而那个 $invert$ 可以看作是先 $swap$,再进行一个镜面翻转.

由于本题有多个标记,所以标记的下传顺序要定好.

我们发现,$invert$ 和 $swap$ 操作是互不干扰的,所以这两个的顺序无所谓.

而 $swap$ 操作和 $replace$ 操作也是互不干扰的.

而 $invert$ 操作会影响 $replace$ 操作.

所以在 $invert $ 的时候将 $replace$ 标记取反就好了.

#include <cstdio> 
#include <map> 
#include <vector>
#include <cstring> 
#include <string>
#include <algorithm>   
#define N 100007  
#define ll long long        
#define lson s[x].ch[0] 
#define rson s[x].ch[1] 
using namespace std;       
char str[N];  
int root,tot,A[N];  
struct Splay
{   
    int ch[2],f,sum[2][2];    
    int swa,inv,tag,w,siz; 
}s[N];     
// (->-1, )->+1     
int get(int x) { return s[s[x].f].ch[1]==x; }  
void mark_swa(int x) 
{                    
    swap(lson,rson);   
    swap(s[x].sum[0][0],s[x].sum[1][1]); 
    swap(s[x].sum[0][1],s[x].sum[1][0]);   
    s[x].swa^=1;    
}    
void mark_inv(int x) 
{     
    s[x].w=-s[x].w; 
    s[x].tag=-s[x].tag;    
    swap(s[x].sum[0][0],s[x].sum[1][0]);   
    swap(s[x].sum[0][1],s[x].sum[1][1]);    
    s[x].inv^=1;   
}   
void mark_tag(int x,int v)     
{   
    s[x].w=s[x].tag=v;     
    if(v==1) 
    {
        s[x].sum[0][0]=s[x].sum[1][1]=s[x].siz; 
        s[x].sum[0][1]=s[x].sum[1][0]=0;  
    }  
    else 
    {
        s[x].sum[0][1]=s[x].sum[1][0]=s[x].siz;  
        s[x].sum[0][0]=s[x].sum[1][1]=0;   
    }
}
void pushup(int x) 
{ 
    int l=lson,r=rson;     
    s[x].siz=s[lson].siz+s[rson].siz+1;    
    // 00 与 11,10 与 01      
    s[x].sum[0][0]=s[l].sum[0][0]+max(0,s[r].sum[0][0]-s[l].sum[0][1]+s[x].w);    // )
    s[x].sum[0][1]=s[r].sum[0][1]+max(0,s[l].sum[0][1]-s[r].sum[0][0]-s[x].w);    // (                                  
    s[x].sum[1][0]=s[l].sum[1][0]+max(0,s[r].sum[1][0]-s[l].sum[1][1]-s[x].w);    // (
    s[x].sum[1][1]=s[r].sum[1][1]+max(0,s[l].sum[1][1]-s[r].sum[1][0]+s[x].w);    // ) 
}  
void pushdown(int x) 
{
    if(s[x].swa) 
    {
        if(lson) mark_swa(lson); 
        if(rson) mark_swa(rson); 
        s[x].swa=0; 
    }  
    if(s[x].inv) 
    {
        if(lson) mark_inv(lson); 
        if(rson) mark_inv(rson); 
        s[x].inv=0; 
    }   
    if(s[x].tag) 
    {
        if(lson) mark_tag(lson,s[x].tag); 
        if(rson) mark_tag(rson,s[x].tag);  
        s[x].tag=0;   
    }
}
void rotate(int x) 
{
    int old=s[x].f,fold=s[old].f,which=get(x);  
    s[old].ch[which]=s[x].ch[which^1]; 
    if(s[old].ch[which]) s[s[old].ch[which]].f=old; 
    s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;   
    if(fold) s[fold].ch[s[fold].ch[1]==old]=x;   
    pushup(old),pushup(x);   
}     
void splay(int x,int &tar) 
{
    int u=s[tar].f,fa; 
    for(;(fa=s[x].f)!=u;rotate(x)) 
        if(s[fa].f!=u) rotate(get(fa)==get(x)?fa:x);  
    tar=x;  
}
int find(int x,int kth) 
{
    pushdown(x);   
    if(s[lson].siz>=kth) return find(lson,kth);   
    else if(s[lson].siz+1==kth) return x;  
    else return find(rson,kth-s[lson].siz-1);    
}         
int split(int x,int y) 
{     
    int l=find(root,x);    
    splay(l,root);    
    int r=find(root,y+2);   
    splay(r,s[root].ch[1]);   
    int tmp=s[s[root].ch[1]].ch[0];     
    return tmp;   
}    
void build(int &x,int l,int r,int ff) 
{
    x=++tot;   
    s[x].f=ff;   
    int mid=(l+r)>>1;  
    s[x].w=A[mid];           
    if(l<mid) build(lson,l,mid-1,x);   
    if(r>mid) build(rson,mid+1,r,x);   
    pushup(x);     
}
void setIO(string s) { freopen((s+".in").c_str(),"r",stdin); }       
int main() 
{   
    // setIO("input"); 
    int i,j,n,Q;           
    scanf("%d%d%s",&n,&Q,str+1);      
    for(i=2;i<=n+1;++i) A[i]=str[i-1]=='('?-1:1;      
    build(root,1,n+2,0);   
    for(i=1;i<=Q;++i) 
    {   
        char op[10]; 
        scanf("%s",op);    
        int x,y; 
        char z;  
        if(op[0]=='R') 
        {    
            scanf("%d%d%s",&x,&y,op);       
            int p=split(x,y);   
            if(op[0]==')') mark_tag(p,1);   
            else mark_tag(p,-1);                    
            while(s[p].f) pushup(s[p].f),p=s[p].f;  
        } 
        if(op[0]=='S') 
        {     
            scanf("%d%d",&x,&y);   
            int p=split(x,y);   
            mark_swa(p); 
            while(s[p].f) pushup(s[p].f),p=s[p].f;    
        }  
        if(op[0]=='I') 
        {   
            scanf("%d%d",&x,&y);   
            int p=split(x,y);   
            mark_inv(p);  
            while(s[p].f) pushup(s[p].f),p=s[p].f;    
        } 
        if(op[0]=='Q') 
        {  
            int x,y; 
            scanf("%d%d",&x,&y);   
            int p=split(x,y);    
            printf("%d\n",(s[p].sum[0][0]+1)/2+(s[p].sum[0][1]+1)/2);         
        }
    }
    return 0;
}

  

posted @ 2020-01-07 20:52  EM-LGH  阅读(169)  评论(0编辑  收藏  举报