编程之美-平衡树·SBT

http://hihocoder.com/problemset/problem/1337

#1337 : 平衡树·SBT

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Ho:小Hi,之前你不是讲过Splay和Treap么,那么还有没有更简单的平衡树呢?

小Hi:但是Splay和Treap不是已经很简单了么?

小Ho:是这样没错啦,但是Splay和Treap和原来的二叉搜索树相比都有很大的改动,我有点记不住。

小Hi:这样啊,那我不妨再给你讲解一个新的平衡树算法好了。和二叉搜索树相比,它只需要修改insert函数,就可以做到高度的平衡。

小Ho:好,我就喜欢这样的!

提示:Size Balanced Tree

输入

第1行:1个正整数n,表示操作数量,10≤n≤100,000

第2..n+1行:每行1个字母c和1个整数k:

若c为‘I‘,表示插入一个数字k到树中,-1,000,000,000≤k≤1,000,000,000

若c为‘Q‘,表示询问树中第k小数字,保证1≤k≤树的节点数量

输出

若干行:每行1个整数,表示针对询问的回答,保证一定有合法的解

样例输入
5
I 3
I 2
Q 1
I 5
Q 2
样例输出
2
3

---恢复内容结束---

动态查询Ktop系列

1.对于固定的Ktop系列,可以使用 优先队列,最小堆,Treap,BST,SBT

2.动态的Ktop Treap,BST,SBT 效率: BST<Treap<SBT

解法一 使用二叉搜索树:

 1 import java.util.Scanner;
 2
 3 /**
 4  * author: 龚细军
 5  * class-aim:
 6  */
 7
 8 class Node {
 9     public Integer key;
10     public long size;
11     public Node left;
12     public Node right;
13
14     public Node() {
15         size = 0;
16         key = null;
17         left = right = null;
18     }
19 }
20
21 /*二叉排序树,此题不需要调解平衡*/
22 class BSTree {
23     private static final int DEFAULT_INITIAL_CAPACITY = 1;
24
25     public static int query(Node node, int kMin) {
26         Long flag = node.left.size - kMin + 1;
27         if (flag == 0) return node.key;
28         if (flag < 0) return query(node.right, (int) abs(flag));
29         return query(node.left, kMin);
30     }
31
32     private static long abs(Long flag) {
33         return flag > 0 ? flag : -1 * flag;
34     }
35
36     public static void insert(Node node, int data) {
37         if (node.size > 0) {
38             node.size++;
39             insert(data > node.key ? node.right : node.left, data);
40         } else {
41             node.key = data;
42             node.size = DEFAULT_INITIAL_CAPACITY;
43             node.left = new Node();
44             node.right = new Node();
45         }
46     }
47
48 }
49
50 public class Main {
51
52     public static void main(String args[]) {
53         int num, val;
54         String cmd;
55         Scanner scanner = new Scanner(System.in);
56         while (scanner.hasNext()) {
57             num = scanner.nextInt();
58             Node root = new Node();
59             while (num-- > 0) {
60                 cmd = scanner.next();
61                 val = scanner.nextInt();
62                 if (cmd.equals("I")) BSTree.insert(root, val);
63                 else {
64                     System.out.println(BSTree.query(root, val));
65                 }
66             }
67         }
68     }
69
70 }

解法二: SBT树

  1 import java.util.Scanner;
  2
  3 /**
  4  * author: 龚细军
  5  * class-aim:
  6  */
  7
  8 class Node {
  9     public int key, size;
 10     public Node left, right;
 11 }
 12
 13 public class Main {
 14     private static final int DEFAULT_INITIAL_CAPACITY = 1;
 15
 16     public static int getSize(Node node) {
 17         return node == null ? 0 : node.size;
 18     }
 19
 20     public static int compare(Node a, Node b) {
 21         return a.key - b.key;
 22     }
 23
 24     public static int compare(Node a, int key) {
 25         return a.key - key;
 26     }
 27
 28     public static void update(Node node) {
 29         if (node == null) return;
 30         node.size = getSize(node.left) + getSize(node.left) + 1;
 31     }
 32
 33     public static void rightRotate(Node master, Node node) {
 34         master.left = node.right;
 35         node.right = master;
 36         update(master);
 37         update(node);
 38         master = node;
 39     }
 40
 41     public static void leftRotate(Node master, Node node) {
 42         master.right = node.left;
 43         node.left = master;
 44         update(node);
 45         update(master);
 46         master = node;
 47     }
 48
 49     public static void insert(Node master, int key) {
 50
 51         if (master.size == 0) {
 52             master.left = new Node();
 53             master.right = new Node();
 54             master.size = DEFAULT_INITIAL_CAPACITY;
 55             master.key = key;
 56         } else if (compare(master, key) > 0) {
 57             insert(master.left, key);
 58             if (getSize(master.left.left) > getSize(master.right)) {
 59                 //右旋转
 60                 rightRotate(master, master.left);
 61             }
 62         } else {
 63             insert(master.right, key);
 64             if (getSize(master.right.right) > getSize(master.left)) {
 65                 //左旋转
 66                 leftRotate(master, master.right);
 67             }
 68         }
 69
 70         update(master);
 71
 72     }
 73
 74     private static int abs(int flag) {
 75         return flag > 0 ? flag : -1 * flag;
 76     }
 77
 78     public static int query(Node node, int kMin) {
 79         int flag = node.left.size - kMin + 1;
 80         if (flag == 0) return node.key;
 81         if (flag < 0) return query(node.right, (int) abs(flag));
 82         return query(node.left, kMin);
 83     }
 84
 85     public static void main(String args[]) {
 86         int num, val;
 87         String cmd;
 88         Scanner scanner = new Scanner(System.in);
 89         while (scanner.hasNext()) {
 90             num = scanner.nextInt();
 91             Node root = new Node();
 92             while (num-- > 0) {
 93                 cmd = scanner.next();
 94                 val = scanner.nextInt();
 95                 if (cmd.equals("I"))
 96                     Main.insert(root, val);
 97                 else
 98                     System.out.println(Main.query(root, val));
 99             }
100         }
101     }
102 }
时间: 2024-10-11 17:56:19

编程之美-平衡树·SBT的相关文章

编程之美-分层遍历二叉树

问题:给定一个二叉树,要求按分层遍历该二叉树,即从上到下按层次访问该二叉树(每一层将单独输出一行),每一层要求访问的顺序为从左到右,并将节点依次编号.那么分层遍历如图的二叉树,正确的输出应该为: <span style="font-size:14px;">1 2 3 4 5 6 7 8</span> 书中还给出了问题2:打印二叉树中的某层次的节点(从左到右),其中根结点为第0层,成功返回true,失败返回false 分析与解法 关于二叉树的问题,由于其本身固有的

读书问题之《编程之美》 -----12061161 赵梓皓

我阅读的书是<编程之美> 刚开始的时候阅读序,就觉得控制cpu利用率这个问题很好玩,所以重点看了这部分和解决办法,问题也都大部分是这部分的.那么问题就来了(挖掘机技术xxx?中国山东找蓝翔) 咳咳,问题在下面: 1.关于问题的提出.(也是一点点建议) 本书的主要内容是告诉读者如何思考问题和解决问题.但是提出问题也是很重要的,正如爱因斯坦所说“提出一个问题往往比解决一个问题更重要”,很多面试题(比如井盖为啥是圆的)我觉得正常人很少会想到.所以,这个问题是怎么想出来的...我很好奇.也希望作者能够

《编程之美》3.6判断链表是否相交之扩展:链表找环方法证明

先看看原题:<编程之美>3.6编程判断两个链表是否相交,原题假设两个链表不带环. 为了防止剧透使得没看过原题目的读者丧失思考的乐趣,我把最好的解法隐藏起来.由于这个问题本身的解答并不是本文的重点,扩展问题也采用这种形式呈现. 注:位于(*)符号之间的文字出自于:http://blog.csdn.net/v_july_v/article/details/6447013,作者v_JULY_v. 用指针p1.p2分别指向两个链表头,不断后移:最后到达各自表尾时,若p1==p2,那么两个链表必相交 用

编程之美之买票找零

题目:假设有2N个人在排队买票,其中有N个人手持50元的钞票,另外有N个人手持100元的钞票,假设开始售票时,售票处没有零钱,问这2N个人有多少种排队方式,不至使售票处出现找不开钱的局面? 分析:队伍的序号标为0,1,...,2n-1,并把50元看作左括号,100元看作右括号,合法序列即括号能完成配对的序列.对于一个合法的序列,第0个一定是左括号,它必然与某个右括号配对,记其位置为k.那么从1到k-1.k+1到2n-1也分别是两个合法序列.那么,k必然是奇数(1到k-1一共有偶数个),设k=2i

【编程之美】java实现重建二叉树

package com.cn.binarytree.utils; /** * @author 刘利娟 [email protected] * @version 创建时间:2014年7月20日 下午2:03:30 类说明: */ class Node { Node left; Node right; char chValue; Node(char chValue) { left = null; right = null; this.chValue = chValue; } } public cla

编程之美之字符串移位包含问题

[题目] 给定两个字符串s1和s2,要求判断s2是否能够被通过s1做循环移位(rotate)得到的字符串包含.例如,S1=AABCD和s2=CDAA,返回true:给定s1=ABCD和s2=ACBD,返回false. [分析] [思路一] 从题目中可以看出,我们可以使用最直接的方法对S1进行循环移动,再进行字符串包含的判断,从而遍历其所有的可能性. 字符串循环移动,时间复杂度为O(n),字符串包含判断,采用普通的方法,时间复杂度为O(n*m),总体复杂度为O(n*n*m). 字符串包含判断,若采

读《编程之美》读后感

读完<编程之美>后,我觉得这并不是简简单单的一本有关于编程的书,本书强调的不仅仅是程序或者考题本身,而是思维.这就和小学时看到数学奥林匹克竞赛的题一样,重要的不是套路或者定式,而在于独立思考时被自己激活的无数脑细胞.对于程序,也是一样,思维,才是程序的精髓所在.正如作者所言,书中展现的题目和分析,犹如海滩上美丽的石子和漂亮的贝壳那样,反映出造化之美,编程之美.该书的目的不仅在于揭开微软面试的神秘面纱,更是鼓励更多的编程爱好者从中收获自己的想法,开阔自己的眼界.作者更希望让面试者和被面试者都能够

求二进制数中1的个数(编程之美)

求二进制数中1的个数 继京东618店庆时买的<编程之美>这本书,翻了翻,发现里面的题还是挺有意思的,看起来我们觉得很简单的题目,解法却有很多很多种,真是一个比一个巧妙,于是,决定记录一下. 书中的题目如下 对于一个字节(8bit)的无符号数,求其二进制表示中"1"的个数,要求算法的执行效率尽可能高. 就像书中给我们说的一样,我们一般人可能想到的解决方法如下 int countOne(int n){ int count=0; while(n){ if(n%2==1){ cou

求子数组之和的最大值——编程之美 2.14 扩展问题 正确实现

使用动态规划求最大子数字和: s[i]表示data[i~n-1]以元素i开始的最大子数组和,a[i]表示data[i~n-1]中的最大子数组和 : s[i]=max(s[i+1]+data[i], data[i]); a[i]=max(a[i+1], s[i]); 由于数组s,a递推的时候,都只用到数组的前一个变量,所以可以用滚动数组节省空间. 扩展问题: 1) 如果数组首尾相连,即允许找到一组数字(A[i],···,A[n-1], A[0],···, A[j]),请使其和最大,怎么办?(书中答