zoukankan      html  css  js  c++  java
  • HYSBZ 1588 营业额统计 平衡二叉树模板

      题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=1588

      题目描述: 给你N个数, 定义f(i) 为第i个数与i个数绝对值的最小值, 求f(1) + f(2) + f(3) + ....... + f(n)

      解题思路: 如何快速的找到与插入的值差的最小值, 就是左子树的最大值与右子树的最小值的绝对值差值的较小者。 一道平衡二叉树的模板题, 自己也复习了一下数据结构

      代码: 

    /* ***********************************************
    Author        :Kirisame_Marisa
    blog          :http://www.cnblogs.com/KirisameMarisa/
    Created Time  :2015年03月24日 星期二 20时45分12秒
    File Name     :splay.cpp
    ************************************************ */
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <ctime>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    using namespace std;
    const int INF=0x3f3f3f3f;
    const int MAXN=100010;
    #define eps 1e-10
    #define zero(x) (fabs(x)<eps)
    #define REP(X,N) for(int X=0;X<N;X++)
    #define REP2(X,L,R) for(int X=L;X<=R;X++)
    #define CLR(A,X) memset(A,X,sizeof(A))
    #define PB(X) push_back(X)
    #define MP(X,Y) make_pair(X,Y)
    #define IT iterator
    #define test puts("OK")
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    typedef vector<PII> VII;
    
    const int null=-1;
    
    struct node
    {
        int par;
        int cld[2];    //0是左儿子,1是右儿子
        int key;
    } ts[MAXN];
    int root,cnt;
    
    void init()
    {
        root=null;
        cnt=0;
    }
    
    int newnode(int p,int k)
    {
        ts[cnt].key=k;
        ts[cnt].par=p;
        ts[cnt].cld[0]=ts[cnt].cld[1]=null;
        return cnt++;
    }
    
    void rotate(int x,int k)    //k=0为左旋,k=1为右旋
    {
        int y=ts[x].par;
        ts[y].cld[!k]=ts[x].cld[k];
        if(ts[x].cld[k]!=null)
            ts[ts[x].cld[k]].par=y;
        ts[x].par=ts[y].par;
        if(ts[y].par!=null)
        {
            if(y==ts[ts[y].par].cld[0])
                ts[ts[y].par].cld[0]=x;
            else
                ts[ts[y].par].cld[1]=x;
        }
        ts[y].par=x;
        ts[x].cld[k]=y;
    }
    
    void splay(int x,int S)   //伸展操作,将x旋转到目标节点,其中S为目标节点的parent
    {
        while(ts[x].par!=S)
        {
            int p=ts[x].par;
            if(ts[p].par==S)
                rotate(x,ts[p].cld[0]==x);
            else
            {
                int d=(ts[ts[p].par].cld[0]==p);
                if(ts[p].cld[d]==x)
                    rotate(x,!d),rotate(x,d);
                else
                    rotate(p,d),rotate(x,d);
            }
        }
        if(S==-1)
            root=x;
    }
    
    bool insert(int x)
    {
        if(root==null)
        {
            root=newnode(null,x);
            return 1;
        }
        int r=root,pre=null;
        while(r!=null)
        {
            if(ts[r].key==x)
            {
                splay(r,null);     //如果直接找到的话就不新建节点,直接splay
                return 0;
            }
            else
            {
                pre=r;
                r=ts[r].cld[ts[r].key<x];
            }
        }
        int &t=ts[pre].cld[ts[pre].key<x];
        t=newnode(pre,x);
        splay(t,null);
        return 1;
    }
    
    int getlow(int x)         //获取比它小的最大值。由于插入操作x已经被旋转到根节点,所以只要寻找左子树的最大值即可,下同
    {
        int d=ts[root].cld[0];
        if(d==null)
            return INF;
        while(ts[d].cld[1]!=null)
            d=ts[d].cld[1];
        return x-ts[d].key;
    }
    
    int getup(int x)          //获取比它大的最小值
    {
        int d=ts[root].cld[1];
        if(d==null)
            return INF;
        while(ts[d].cld[0]!=null)
            d=ts[d].cld[0];
        return ts[d].key-x;
    }
    
    void debug(int x)
    {
        int l=ts[x].cld[0],r=ts[x].cld[1];
        if(l!=null)
            debug(l);
        printf("id:%2d key:%2d par:%2d lcd:%2d rcd:%2d
    ",x,ts[x].key,ts[x].par,l,r);
        if(r!=null)
            debug(r);
    }
    
    int main()
    {
        //freopen("in","r",stdin);
        //freopen("out","w",stdout);
        init();
        int n,x,sum=0;
        scanf("%d%d",&n,&x);
        sum+=x;
        insert(x);
        REP(i,n-1)
        {
            x=0;
            scanf("%d",&x);
            bool temp=insert(x);
            if(temp)
                sum+=min(getlow(x),getup(x));
        }
        printf("%d
    ",sum);
        return 0;
    }
    模板

      思考: 模板转自http://www.cnblogs.com/KirisameMarisa/p/4366582.html, 感谢墨染之樱花......另外自己也看了看这个splay , 都是很基础的rotate和查询, 就当是回顾一下数据结构

      另外有一篇讲的很好的平衡二叉树文章, 放在这里, 提醒自己时刻进行学习.......前几天发烧了, 是烧的真的严重....但是也看明白了一些事情, 学到了不少东西, 我要努力变强, 这个学校我一分钟也不想待在这里!

  • 相关阅读:
    是否可以继承String类
    访问控制符 public,protected,private,以及默认(default)的区别
    构造器 Constructor 是否可被 override
    重载和重写的区别
    Java 的四个基本特性(抽象、封装、继承, 多态)
    面向对象和面向过程的区别
    Layui时间选择器只选择时和分,不显示秒
    解决JavaScript:Uncaught TypeError: xx(函数名)is not a function at HTMLInputElement.onclick
    Linux(Ubuntu):搭建GitLab托管代码
    【转】【Oracle 集群】Linux下Oracle RAC集群搭建之基本测试与使用(九)
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7545158.html
Copyright © 2011-2022 走看看