zoukankan      html  css  js  c++  java
  • Splay树再学习

    队友最近可能在学Splay,然后让我敲下HDU1754的题,其实是很裸的一个线段树,不过用下Splay也无妨,他说他双旋超时,单旋过了,所以我就敲来看下。但是之前写的那个Splay越发的觉得不能看,所以直接学习了大神的Splay树的写法,下面的代码是CLJ上的Splay模板,有很多值得借鉴的地方,代码量比自己写短好多,下面记录下心得。

    1.结点标记的add,set直接写在结点里面,更容易理解也更容易明白。

    2.pushDown,pushUp也写在Node里,感觉也是漂亮许多。

    3.第一次看到的 Node mem[maxn],*C=mem; 写法,这样就不用每次都 &mem[top++],直接就用C++就好,挺好的。

    4.写一个作为sentinel的null,这个应该也是一个很重要的认识了吧。

    5.旋转和splay两个函数都写的好妙。

    6.用get传出【l,r)的区间的结点,之前没有当成一个函数写不太漂亮。

    附上大神的模板权当学习。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #define INF 0x3fffffff
    #define maxn 200100
    using namespace std;
    
    struct Node
    {
        Node *ch[2],*p;
        int size,val,mx;
        int set; 
        bool rev;
        Node(){
            size=0;
            val=mx=-INF;
            set=-1;
        }
        bool d(){
            return this==p->ch[1];
        }
        void setc(Node *c,int d){
            ch[d]=c;
            c->p=this;
        }
        void setIt(int se){
            set=mx=val=se;
        }
        void revIt(){
            rev^=1;
        }
        void pushDown(); // pushDown();
        void pushUp(){
            size=ch[0]->size+ch[1]->size+1;
            mx=max(val,max(ch[0]->mx,ch[1]->mx));
        }
    }Tnull,*null=&Tnull;
    
    Node mem[maxn+50],*C=mem;
    int a[maxn+50];
    
    void Node::pushDown(){
        if(set!=-1){
            for(int i=0;i<2;++i){
                if(ch[i]!=null) ch[i]->setIt(set);
            }
            set=-1;
        }
        if(rev){
            swap(ch[0],ch[1]);
            for(int i=0;i<2;++i){
                if(ch[i]!=null) ch[i]->revIt();
            }
            rev=0;
        }
    }
    
    Node *make(int v){
        C->ch[0]=C->ch[1]=null;
        C->size=1;
        C->val=C->mx=v;
        C->set=-1;C->rev=0;
        return C++;
    }
    
    Node *build(int l,int r)
    {
        if(l>=r) return null;
        int m=(l+r)>>1;
        Node *t=make(a[m]); // 根据数组建值,建空值则t=make(0);
        t->setc(build(l,m),0);
        t->setc(build(m+1,r),1);
        t->pushUp();
        return t;
    }
    
    Node *root;
    
    void rot(Node *t){
        Node *p=t->p;
        p->pushDown();
        t->pushDown();
        int d=t->d();
        p->p->setc(t,p->d());
        p->setc(t->ch[!d],d);
        t->setc(p,!d);
        p->pushUp();
        if(p==root)
            root=t;
    }
    
    void splay(Node *t,Node *f=null){
        while(t->p!=f){
            if(t->p->p==f){
                rot(t);
            }
            else{
                t->d()==t->p->d()? (rot(t->p),rot(t)):(rot(t),rot(t));
            }
        }
        t->pushUp();
    }
    
    Node *select(int k){
        for(Node *t=root;;){
            t->pushDown();
            int c=t->ch[0]->size;
            if(k==c) {
                return t;
            }
            if(k>c) {
                k-=c+1,t=t->ch[1];
            }
            else{ 
                t=t->ch[0];
            }
        }
    }
    
    Node*&get(int l,int r){ //[l,r)
        Node *L=select(l-1);
        Node *R=select(r);
        splay(L);
        splay(R,L);
        return R->ch[0];
    }
    
    int n,m;
    
    int main()
    {
        while(cin>>n>>m)
        {
            C=mem;
            for(int i=1;i<=n;++i){
                scanf("%d",&a[i]);
            }
            root=build(0,n+2);
            root->p=null;
            char str[3];int l,r;
            for(int i=0;i<m;++i){
                scanf("%s%d%d",str,&l,&r);
                if(strcmp(str,"Q")==0){
                    Node*&t=get(l,r+1);
                    printf("%d
    ",t->mx);
                }
                else{
                    Node*&t=get(l,l+1);
                    t->setIt(r);
                }
            }    
        }
        return 0;
    }
    
  • 相关阅读:
    闭包
    递归 斐波那契
    作用域,函数的四种调用模式
    数组方法
    Math内置对象
    BeanUtils.copyProperties() 用法
    ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) .append("Id",getId())防止内存泄漏
    Spring配置文件applicationContext.xml Hibernate SQL方言 (hibernate.dialect)
    Redis面试总结
    Nginx面试题
  • 原文地址:https://www.cnblogs.com/chanme/p/3494643.html
Copyright © 2011-2022 走看看