zoukankan      html  css  js  c++  java
  • 赤裸裸的splay平衡树

    HYSBZ1588 http://www.lydsy.com/JudgeOnline/problem.php?id=1588

    给我们n天的营业额, 要求出每天的最小波动值,然后加起来。  当天最小波动值 = 当天营业额 - (之前某天与当天营业额最接近的营业额)

    所以维护一个spaly,将当天的营业额x插入splay中,然后将x旋转到根结点,然后找到左子树的最大值,右子树的最小值, 判断哪一个与当天的营业额差值小。

    这里只用到了两种旋转,左旋和右旋。 没有考虑x的服 父亲是不是根节点。 也没有考虑共线不共线的问题。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<string.h>
      4 #include<algorithm>
      5 #include <vector>
      6 #include <math.h>
      7 using namespace std;
      8 const int INF = 0x7FFFFFFF;
      9 const int N = 100000 + 10;
     10 
     11 /*
     12 
     13             int y = pre[x];
     14         pre[next[x][kind]] = y;
     15         next[y][!kind] = next[x][kind];
     16         if(pre[y])
     17             next[pre[y]][next[pre[y]][1]==y] = x;
     18 
     19         //x旋转到了y的位置,所以y的父亲变成了x的父亲
     20         pre[x]  = pre[y];
     21         //
     22         next[x][kind] =  y;
     23         //x变成了y的父亲
     24         pre[y] = x;
     25 */
     26 struct SplayTree{
     27     int size,root;
     28     int next[N][2],pre[N],key[N];
     29     void init()
     30     {
     31         size = root = 0;
     32     }
     33     void newNode(int &rt, int father,int val)
     34     {
     35         rt = ++size;
     36         next[rt][0] = next[rt][1] = 0;
     37         pre[rt] = father;
     38         key[rt] = val;
     39     }
     40     //kind = 0表示左转, 为1表示右转
     41     void rotate(int x, int kind)
     42     {
     43         int y = pre[x];//x的父亲
     44         pre[x] = pre[y];
     45         pre[y] = x;
     46         next[y][!kind] = next[x][kind];
     47         pre[next[y][!kind]] = y;
     48         next[x][kind] = y;
     49         if(pre[x])
     50             next[pre[x]][next[pre[x]][1]==y] = x;
     51     }
     52     //将x旋转为goal的儿子
     53     void splay(int x, int goal)
     54     {
     55         while(pre[x]!=goal)
     56         {
     57             if(next[pre[x]][0] == x)//如果自己的父亲的左孩子
     58                 rotate(x,1);//右转
     59             else//左转
     60                 rotate(x,0);
     61         }
     62         //如果x旋转到了根结点,那么root的指向需要发生变化
     63         if(!goal)
     64             root = x;
     65     }
     66     bool insert(int k)
     67     {
     68         int x,y;
     69         for(x=root;next[x][k>key[x]];x=next[x][k>key[x]])
     70             if(k==key[x])//如有已经有了要插入的结点,那么返回false
     71             {
     72                 splay(x,0);
     73                 return false;
     74             }
     75         newNode(next[x][k>key[x]],x,k);
     76         splay(next[x][k>key[x]],0);
     77         return true;
     78     }
     79     int getPre()//如果有左子树,获得左子树最大值
     80     {
     81         int x = next[root][0];
     82         if(x)
     83         {
     84             while(next[x][1])
     85             {
     86                 x = next[x][1];
     87             }
     88             return key[x];
     89         }
     90         return INF;
     91     }
     92     int getNext()//如果有右子树,获得右子树最小值
     93     {
     94         int x = next[root][1];
     95         if(x)
     96         {
     97             while(next[x][0])
     98             {
     99                 x = next[x][0];
    100             }
    101             return key[x];
    102         }
    103         return INF;
    104     }
    105 };
    106 SplayTree tree;
    107 int main()
    108 {
    109     //将每一天的最小波动值加起来
    110     int n,ans,x,a,b;
    111     while(scanf("%d%d",&n,&ans)!=EOF)
    112     {
    113         tree.init();
    114         tree.newNode(tree.root,0,ans);
    115         while(--n)
    116         {
    117             x = 0;
    118             scanf("%d",&x);
    119 
    120             //返回true,如果没有两个相同的结点,如果有,那么最小波动是0,不用加
    121             if(tree.insert(x))
    122             {
    123                 a = tree.getPre();
    124                 if(a<INF)
    125                     a = x - a;
    126                 b = tree.getNext();
    127                 if(b<INF)
    128                     b  -= x;
    129 
    130                 ans += min(a,b);
    131             }
    132         }
    133         printf("%d
    ",ans);
    134 
    135     }
    136     return 0;
    137 }
  • 相关阅读:
    7种jvm垃圾回收器,这次全部搞懂
    3分钟学会redis主从复制搭建,及原理
    一文搞懂什么是递归,程序员必会算法之一
    Redis持久化方式:RDB和AOF详解,对比
    jvm垃圾回收算法详解,看这一篇就够了(求点赞)
    Redis命令大全,满足你的日常工作,看这一篇就够了(求点赞)
    Java自定义异常为什么性能差(求点赞)阿里双十一的性能凶手之一
    jvm类加载器,类加载机制详解,看这一篇就够了(求点赞)
    show processlist 命令详解,MySQL优化看这一篇就够了
    asp.net中的post和get请求操作
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4894428.html
Copyright © 2011-2022 走看看