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\n",t->mx);
            }
            else{
                Node*&t=get(l,l+1);
                t->setIt(r);
            }
        }    
    }
    return 0;
}

 

posted @ 2013-12-27 18:24  chanme  阅读(391)  评论(0编辑  收藏  举报