初识splay tree (一)

来源:互联网 发布:苏联解体中国反应 知乎 编辑:程序博客网 时间:2024/06/04 18:29

本来是要做hihocoder 1034 毁灭者问题,发现朴素的数据结构无法满足该题目如此BT的要求,随查了一下,splay tree貌似可以解决,于是目标转到了学习splay tree上。
学习splay tree 的主要参考资料:
《伸展树的基本操作与应用》– 杨思雨
《运用伸展树解决数列维护问题》– By Crash
《Splaying a Search Tree in Preorder Takes Linear Time》
《NOI 2005 维护数列》– ByVoid
《NOI 2005 维护数列 测试数据》
太晚了,具体操作原理、细节明天再更新。。
这里先发一个poj3468 A Simple Problem with Integers AC代码,当做初学splay tree的第一道测试题。

#include <iostream>#include <cstdio>#include <cstdlib>using namespace std;#define ll64 long long int struct st{    struct node{        long long int size,value,cover,sums;        struct node *pre,*ch[2];    };      node *nill,*root;    node buf[200000]; int bufsize;    int pushdown(node *x){        if(x==nill || x==NULL) return 0;        if(x->cover){            x->value+=x->cover; x->sums+=x->cover*x->size;             x->ch[0]->cover+=x->cover;            x->ch[1]->cover+=x->cover;            x->cover=0;        }        return 0;    }    int update(node *x){        if(x==nill || x==NULL) return 0;        pushdown(x->ch[0]);pushdown(x->ch[1]);        x->size = x->ch[0]->size+x->ch[1]->size+1;        x->sums=x->ch[0]->sums+x->ch[1]->sums+x->value;        return 0;    }    node *getnode(ll64 value,node *fa){        node *p=buf+bufsize++;        p->cover=0;        p->value=p->sums=value;        p->size=1;        p->ch[0]=p->ch[1]=nill; p->pre=fa;        return p;    }    int init(){        bufsize=0; nill=root=NULL;        nill=getnode(0,NULL);        nill->size=0; nill->ch[0]=nill->ch[1]=NULL;        root=getnode(0,nill);        root->ch[1]=getnode(0,root);        return 0;    }    int rotateto(node*x,int to){        node *y=x->pre;        y->ch[to^1]=x->ch[to];        y->ch[to^1]->pre=y;        x->pre=y->pre;        if(y==y->pre->ch[0])x->pre->ch[0]=x;        else x->pre->ch[1]=x;        x->ch[to]=y; y->pre=x;        update(y);        if(y==root) root=x;        return 0;    }    int splay(node *x,node *fa){        pushdown(x);        while(x->pre!=fa ){            if(x->pre->pre==fa){                if(x->pre->ch[0]==x) rotateto(x,1);                else rotateto(x,0);            }else{                if(x->pre->pre->ch[0]==x->pre){                    if(x->pre->ch[0]==x){rotateto(x->pre,1);rotateto(x,1);}                    else{rotateto(x,0);rotateto(x,1);}                }else{                    if(x->pre->ch[0]==x){rotateto(x,1);rotateto(x,0);}                    else{rotateto(x->pre,0);rotateto(x,0);}                }            }        }        update(x);        return 0;    }    int select(int k,node *fa){        node *rt=root;        while(rt!=nill){            pushdown(rt);            if(rt->ch[0]->size == k-1) break;            else if(rt->ch[0]->size>k-1) rt=rt->ch[0];            else {k-=rt->ch[0]->size+1; rt=rt->ch[1];}        }        splay(rt,fa);        return 0;    }    int insert(int pos,int tot){        node *p,*q;        long long int s;        scanf("%lld",&s);        p=q=getnode(s,nill);        for(int i=1;i<tot;i++){            scanf("%lld",&s);            p=p->ch[1]=getnode(s,p);        }        select(pos+1,nill);        select(pos+2,root);        root->ch[1]->ch[0]=q; q->pre=root->ch[1];        splay(p,nill);        return 0;    }    int add(int a,int b,long long int c){        select(a,nill);        select(b+2,root);        root->ch[1]->ch[0]->cover+=c;        splay(root->ch[1]->ch[0],nill);        return 0;    }    ll64 getsums(int a,int b){        select(a,nill);        select(b+2,root);    //  cout<<root->value<<" "<<root->ch[1]->value<<endl;        pushdown(root->ch[1]->ch[0]);        return root->ch[1]->ch[0]->sums;    }};int main(){    int n,q;    scanf("%d %d",&n,&q);    st *str=new st;    str->init();    str->insert(0,n);    char s[10]; ll64 c;    int a,b;    for(int i=0;i<q;i++){        scanf("%s %d %d",s,&a,&b);        //cout<<s<<" "<<a<<" "<<b<<endl;        if(s[0]=='Q'){            printf("%lld\n",str->getsums(a,b));        }else{            scanf("%lld",&c);            str->add(a,b,c);        }       }    return 0;}

同时还查到了一个有意思的问题,在这里记下:
《动态树问题及其应用》

0 0
原创粉丝点击