zoukankan      html  css  js  c++  java
  • UOJ#31. 【UR #2】猪猪侠再战括号序列 splay

    显然可以直接凑左面全是左括号,右面全是右括号的情况.   

    然后区间翻转就用 splay 模拟好了.  

    splay 的时候一定注意一点:  

    如果没有调用 find(x),就一定要手动把 x 及其祖先的节点 pushdown. 

    code; 

    #include <bits/stdc++.h>     
    #define N 100009   
    #define ll long long  
    #define lson s[x].ch[0] 
    #define rson s[x].ch[1] 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;
    char str[N<<1];  
    int n,tot,root,A[N<<1],sta[N<<1];   
    struct node { 
        int ch[2],rev,f,w,pos,si;          
    }s[N<<1];            
    int get(int x) { return s[s[x].f].ch[1]==x; }           
    void mark(int x) 
    {
        swap(lson,rson),s[x].rev^=1;             
    }   
    void pushup(int x) 
    {
        int l=lson,r=rson;   
        s[x].si=s[l].si+s[r].si+1;                                          
        if(s[x].w==1) s[x].pos=x;   
        else s[x].pos=0;              
        if(s[l].pos)  s[x].pos=s[l].pos;             
        if(s[r].pos)  s[x].pos=s[r].pos;                   
    }    
    void pushdown(int x) 
    {      
        if(s[x].rev) {
            if(lson) mark(lson); 
            if(rson) mark(rson);  
            s[x].rev=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 fa,u=x,v=0; 
        for(sta[++v]=u;u!=tar;u=s[u].f) sta[++v]=s[u].f;              
        for(;v;--v) pushdown(sta[v]);   
        for(u=s[u].f;(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].si+1==kth) return x;   
        else
        {
            if(s[lson].si>=kth) return find(lson,kth);   
            else return find(rson,kth-s[lson].si-1);  
        }  
    }       
    int build(int l,int r,int ff) 
    {     
        int mid=(l+r)>>1;  
        int cur=++tot;    
        s[cur].f=ff;   
        s[cur].w=A[mid];       
        if(mid>l) s[cur].ch[0]=build(l,mid-1,cur);   
        if(r>mid) s[cur].ch[1]=build(mid+1,r,cur);    
        pushup(cur);   
        return cur;  
    }            
    int cnt;  
    int tl[N],tr[N];   
    int main() 
    { 
        // setIO("input");
        scanf("%s",str+1),n=strlen(str+1);   
        for(int i=1;i<=n;++i) A[i]=(str[i]=='('?1:-1);
        root=build(0,n+1,0);                 
        for(int i=1;i<=n/2;++i) 
        {        
            int CUR;        
            splay(CUR=find(root,i+1),root);                                  
            if(s[root].w==1) continue;     
            else{                                  
                int PRE=find(root,i);            
                splay(PRE,root);     
                int z=s[s[PRE].ch[1]].pos;      
                splay(z,root);      
                int k=s[s[z].ch[0]].si+1;   
                splay(PRE,root);       
                splay(find(root,k+1),s[PRE].ch[1]);    
                int tmp=s[s[PRE].ch[1]].ch[0];    
                mark(tmp);  
                ++cnt;   
                tl[cnt]=i,tr[cnt]=k-1;  
            }
        }
        printf("%d
    ",cnt);        
        for(int i=1;i<=cnt;++i) printf("%d %d
    ",tl[i],tr[i]);      
        return 0; 
    }
    

      

  • 相关阅读:
    扩展Dijkstra
    CodeForces 1396E. Distance Matching
    大联盟2
    整式乘除法
    美国数学会众多教授推荐的本科&研究生代数几何经典书籍教材清单
    算法题——立方体的体对角线穿过多少个正方体?
    导数练习题
    导数压轴题
    集合
    著名数学家Ky Fan的故事
  • 原文地址:https://www.cnblogs.com/guangheli/p/13156029.html
Copyright © 2011-2022 走看看