1588: [HNOI2002]营业额统计(Splay树入门)

来源:互联网 发布:mac mini 2014 换内存 编辑:程序博客网 时间:2024/05/02 05:06

题目的连接
今天开始学习splay树,如cxlove大神所说,开始主要追随别人的代码,然后写出适合自己的,学习的话可以参考kuangbin的这篇文章,及里面提及的论文

#include<cstdio>#include<algorithm>using namespace std;const int maxn=100005;const int inf=1<<28;int pre[maxn],key[maxn],ch[maxn][2],root,tot1;//父亲的节点,键值,左右儿子,根,用于newnode产生节点的计数器int n;void NewNode(int &r,int father,int k){//生成新的节点,节点的父亲是father,关键值是key    r=++tot1;    pre[r]=father;    key[r]=k;    ch[r][0]=ch[r][1]=0;//左右儿子开始是空}void Rotate(int x,int kind){//kind==0表示左旋(是指x绕父节点左旋),kind==1表示右旋    int y=pre[x];    ch[y][!kind]=ch[x][kind];    pre[ch[x][kind]]=y;    if(pre[y])ch[pre[y]][ch[pre[y]][1]==y]=x;    pre[x]=pre[y];    ch[x][kind]=y;    pre[y]=x;}void Splay(int x,int goal){//进行伸展的操作    while(pre[x]!=goal){        if(pre[pre[x]]==goal){            Rotate(x,ch[pre[x]][0]==x);        }        else {            int y=pre[x];            int kind=ch[pre[y]][0]==y;            if(ch[y][kind]==x){//方向不一致,做两次方向不同的旋转                Rotate(x,!kind);                Rotate(x,kind);            }            else {//方向一样,两次相同的旋转                Rotate(y,kind);                Rotate(x,kind);            }        }    }    if(goal==0)root=x;//更新父节点}int Insert(int k){//插入一个键值    int r=root;    while(ch[r][key[r]<k]){        if(key[r]==k){//避免重复插入            Splay(r,0);            return 0;        }        r=ch[r][key[r]<k];    }    NewNode(ch[r][key[r]<k],r,k);    Splay(ch[r][key[r]<k],0);    return 1;}int get_pre(int x){//找X的前驱    int tmp=ch[x][0];    if(tmp==0)return inf;    while(ch[tmp][1])        tmp=ch[tmp][1];    return key[x]-key[tmp];}int get_next(int x){//找X的后继    int tmp=ch[x][1];    if(!tmp) return inf;    while(ch[tmp][0])        tmp=ch[tmp][0];    return key[tmp]-key[x];}int main(){    while(scanf("%d",&n)!=EOF){        root=tot1=0;        int ans=0;        for(int i=1;i<=n;i++){            int num;            if(scanf("%d",&num)==EOF) num=0;            if(i==1){                ans+=num;                NewNode(root,0,num);                continue;            }            if(Insert(num)==0)continue;            int a=get_next(root);            int b=get_pre(root);            ans+=min(a,b);        }        printf("%d\n",ans);    }    return 0;}
0 0