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;
    }
    

      

  • 相关阅读:
    UVa 1451 Average (斜率优化)
    POJ 1160 Post Office (四边形不等式优化DP)
    HDU 3507 Print Article (斜率DP)
    LightOJ 1427 Substring Frequency (II) (AC自动机)
    UVa 10245 The Closest Pair Problem (分治)
    POJ 1741 Tree (树分治)
    HDU 3487 Play with Chain (Splay)
    POJ 2828 Buy Tickets (线段树)
    HDU 3723 Delta Wave (高精度+calelan数)
    UVa 1625 Color Length (DP)
  • 原文地址:https://www.cnblogs.com/guangheli/p/12163669.html
Copyright © 2011-2022 走看看