zoukankan      html  css  js  c++  java
  • 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
    ",(s[p].sum[0][0]+1)/2+(s[p].sum[0][1]+1)/2);         
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    python:返回函数,闭包
    对象的行为和数组
    类、对象和包
    Java语言中的程序流程控制
    初识Java,Java语言概述
    有限广播地址与直接广播地址
    H3C模拟器HCL注意事项
    HDLC协议
    NETBIOS的作用
    HP DL380G7 RAID配置
  • 原文地址:https://www.cnblogs.com/guangheli/p/12163669.html
Copyright © 2011-2022 走看看