More Data Structures: Binary Search Trees and Binary Indexed (Fenwick) Trees Remember how Pinball could be solved using Binary Search? The problem was inserting it into the list took O(n) time, resulting on a running time of O(n2log n) One solution was to sort the list via Mergesort and count the number of times each element was shifted to the left (see Module 1.1.docx at http://files.dmoj.ca/senior or on the Facebook Group) Another solution was by using a Binary Search Tree With a Binary Search Tree, one can insert an element in log n time. Search: (http://algs4.cs.princeton.edu/32bst/) For solving Pinball, we’ll only need to make a BST with Insertion The idea of a BST is fairly simple, however, implementing it is slightly more difficult: Java Implementation: Each element has one parent and two children. If any of these are missing, they will be represented with “null”. For insertion, the procedure is first to search for the element we wish to add to obtain the node to insert it into. We insert it, and then we recursively move it upwards as to keep the BST property. Pseudo code: Always insert new node as leaf node 2. Start at root node as current node 3. If new node’s key < current’s key a. If current node has a left child, search left b. Else add new node as current’s left child 3. If new node’s key > current’s key a. If current node has a right child, search right. b. Else add new node as current’s right child Implementing a Binary Search Tree is left as an exercise to the reader. A Java solution to Pinball can be found in http://files.dmoj.ca/senior, although since it is not balanced, it does not get AC. Remember Selective Cutting from the November DMOPC? It was easy to get prefix sum in Deforestation (P4), but what if there are many queries where you count the mass of only some of the trees within that specified range? One way to solve it is by using Binary Index Trees – also known as Fenwick Trees! A Fenwick Tree is a magical data structure that allows us to add an element into an array and to update the prefix sums of all the elements to the right in O (log N) time! Moreover, a query can be processed in O (log N) time. This leads to a runtime complexity of O(NlogN + QlogN). The idea is to sort the queries from greatest to least. Set up a Fenwick Tree and add for every m, from 20,000 to 1, add all the trees of that mass. Once finished adding all trees of mass m, respond to all queries where q (m) = m. Tree of Responsibility: 1111 1110 Bitwise Operators: & - if both bits are 1, returns 1. Otherwise, 0 1101 | - if either bit is 1, return 1. Otherwise, 0 1100 Example: Insertion 1011 While Index<N 1010 5 | (5+1) = 7 101 | 110 = 111 1001 7 | (7+1) = 15 1000 0111 | 1000 = 1111 111 Example: Querying 110 Cumulative sum at index 6: 101 While Index>=0 6 & (6+1) – 1 = 5 100 110 & 111 - 1 = 110 – 1 = 101 11 5 & (5+1) – 1 = 3 10 101 & 110 – 1 = 100 – 1 = 11 1 3 & (3+1) -1 = -1 0 11 & 100 – 1 = 000 – 1