初涉Splay Tree

Splay Tree 支持的之中操作。

插入,删除,求前驱和后即,区间更新与查询。

先来一发Splay Tree最基础的操作——伸展,顺便求前驱和后即。[HNOI2002]营业额统计。

白书上讲的貌似要讨论目标节点,父节点,父节点的父节点,这三个节点之间的关系。

没太看懂,直接按照自己想得来了。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long LL
#define _LL __int64
#define _INF 0x3f3f3f3f
#define Mod 1000000007

using namespace std;

const int MAXN = 100100;

struct N
{
    int data,son[2],pre;
}st[MAXN*2];

int Top;

void Rotate(int root,int pre,int dir)
{
    N temp = st[pre];
    temp.son[dir] = st[root].son[!dir];
    st[pre] = st[root];
    st[pre].son[!dir] = root;
    st[root] = temp;

    st[pre].pre = temp.pre;

    st[st[pre].son[0]].pre = pre;
    st[st[pre].son[1]].pre = pre;
    st[st[root].son[0]].pre = root;
    st[st[root].son[1]].pre = root;
}

//将目标节点旋转到goal下面,若goal == -1,则表示为将目标节点旋转到根节点。
void Splay(int root,int goal)
{
    while(st[root].pre != goal)
    {
        Rotate(root,st[root].pre,st[st[root].pre].son[0] == root ? 0 : 1);
        root = st[root].pre;
    }
}

bool Insert(int &root,int x,int pre)
{
    if(root == -1 || st[root].data == -1)
    {
        if(root == -1)
            root = Top++;

        st[root].pre = pre;
        st[root].data = x;
        st[root].son[0] = -1;
        st[root].son[1] = -1;

        if(x != -1)
        {
            Insert(st[root].son[0],-1,root);
            Insert(st[root].son[1],-1,root);
            Splay(root,-1);
        }

        return true;
    }

    if(x == st[root].data)
        return false;

    if(x < st[root].data)
        return Insert(st[root].son[0],x,root);
    else
        return Insert(st[root].son[1],x,root);
}

int Search_Min(int root)
{
    if(st[st[root].son[0]].data == -1)
        return st[root].data;
    return Search_Min(st[root].son[0]);
}

int Search_Max(int root)
{
    if(st[st[root].son[1]].data == -1)
        return st[root].data;
    return Search_Max(st[root].son[1]);
}

int main()
{
    //freopen("data.txt","r",stdin);
    int n,x,i;

    int root;

    int sum;

    int MAX = ((1<<30)-1)*2+1;

    scanf("%d",&n);
    sum = 0;
    root = -1;

    for(i = 1; i <= n; ++i)
    {
        if(scanf("%d",&x) == EOF)
            x = 0;

        if(Insert(root,x,-1) == false)
            continue;

        int temp = MAX;

        if(st[st[root].son[0]].data != -1)
            temp = min(temp,abs(Search_Max(st[root].son[0])-st[root].data));
        if(st[st[root].son[1]].data != -1)
            temp = min(temp,abs(Search_Min(st[root].son[1])-st[root].data));
        sum += (temp == MAX ? x : temp);

    }

    printf("%d\n",sum);

    return 0;
}

初涉Splay Tree

时间: 2024-10-20 15:18:24

初涉Splay Tree的相关文章

splay tree旋转操作 hdu 1890

很神奇的旋转操作. 目前没看到其他数据结构能实现这个功能.平衡树不好处理区间操作,线段树很难旋转.splay tree搞这个就很简单了. 下面用的这个模板跑了700ms,好慢,估计是删除操作太费时了,是时候去找找其他更快的模板了. #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define MAXN 1

splay tree成段更新,成段查询poj3466

线段树入门题,换成splay tree 来搞搞. #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; #define MAXN 200100 long long Add[MAXN];//延迟标记 struct Splay_Tree { int cnt, rt;//cnt为节点数,rt == root struc

Splay Tree

伸展树 和AVL树不一样,伸展树并不保证每次操作的时间复杂度为O(logn),而保证任何一个m个操作的序列总时间为O(mlogn).伸展树的基本思想是:每个结点被访问时,使用AVL树的旋转操作把它移动到根.由于旋转是自底向上的,所以需要设置父亲指针,而不像AVL树那样以儿子为轴旋转.伸展操作(splaying) 伸展树的核心是伸展操作Splay(x,S).它是在保持伸展树有序性的前提下,通过一系列旋转将伸展树S中的元素x调整到树的根部.在调整的过程中,要根据x的位置分以下三种情况分别处理.情况一

Splay Tree的删除操作

Splay Tree的插入操作,搜索操作,和删除操作都实现了,那么就可以使用来解题了. 指针的删除操作的处理还是那么难的,很多坎需要避开. 同一个坎还是坑了我好多次,就是指针传递的问题,什么时候需要修改指针本身的值,就必须返回指针或者传递指针的指针,或者传递指针的的实参. 这里的删除操作就是需要改变传递到函数的指针本身的,所以我这里使用了返回指针操作. 还有删除树的问题,之前的代码没做删除操作,所以没问题,现在需要逐个节点删除,所以要小心不能把整个树都删除了. 至此, splay 树的功能差不多

Geeks Splay Tree Insert 树的插入操作

Splay树的插入操作,只需要处理好插入节点的孩子节点就可以了,最重要的是不要破坏了BST的基本规则. 因为高度并不是Splay树的首要因素,所以插入的时候也是使用splay操作,然后在根节点插入. 参考:http://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/ 对比一下使用插入创建的树和手工创建数的区别,先序遍历的结果: #pragma once #include<stdio.h> #include <stdlib.h&g

bzoj 3223/tyvj 1729 文艺平衡树 splay tree

原题链接:http://www.tyvj.cn/p/1729 这道题以前用c语言写的splay tree水过了.. 现在接触了c++重写一遍... 只涉及区间翻转,由于没有删除操作故不带垃圾回收,具体如下: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<iostream> 4 #include<algorithm> 5 const int MAX_N = 100010; 6 struct Node{ 7

树-伸展树(Splay Tree)

伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二叉查找树,即它具有和二叉查找树一样的性质:假设x为树中的任意一个结点,x节点包含关键字key,节点x的key值记为key[x].如果y是x的左子树中的一个结点,则key[y] <= key[x]:如果y是x的右子树的一个结点,则key[y] >= key[x]. (02) 除了拥有二叉查找树的性质

Splay Tree(伸展树)

参考:<数据结构(C++语言版)>邓俊辉著 (好书 一. 伸展树(由 D. D. Sleator 和 R. E. Tarjan 于 1985 年发明)也是平衡二叉搜索树的一种形式.相对于 AVL 树,伸展树的实现更为简洁 伸展树无需时刻都严格地保持全树的平衡,但却能够在任何足够长的真实操作序列中,保持分摊意义上的高效率 伸展树也不需要对基本的二叉树节点结构做任何附加的要求或改动,更不需要记录平衡因子或高度之类的额外信息,故适用范围更广 二.局部性 信息处理的典型模式是,将所有的数据项视作一个集

BZOJ1588 营业额统计 splay tree

最基本的平衡树操作吧,第一次学splay的可以做一下 只需要插入,删除,旋转,求前驱,后继这5个操作吧 不喜欢用指针,用数组写的 <span style="color:#00cccc;">//HNOI2002营业额统计 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #define INF 1<<30 #define