Advanced Data Structures Workshop in Competitive Programming 234900 Introduction

• Many problems can be solved by using an appropriate data structure as a “black-box”. • Basic data structures are implemented in STL – The goal of this presentation is to introduce additional useful data structures which can be easily implemented. • The attached .cpp file contains examples of basic implementaion. /Prefix

• Problem: Given a long string � and a collection of short strings �, … , � , find which of the short strings are contained in �.

• Naive approach: For each short string �, check all possible locations. • Time complexity: � � ⋅ ∑ �

• Faster approach: Construct a Trie • Time complexity: � � + ∑ � Trie/Prefix Tree

• Tire is a which efficiently stores prefixes of strings. It supports the following operations: • Insert(�) – insert string � to the data structure. • Delete(�) – delete string � from the data structure. • Find(�) – return true iff a � is a prefix of a string that was previously inserted. • FindMin(�) – Find the lexicographically-smallest string in the data structure.

• A Trie can be quickly implemented using a matrix, as demonstrated in the attached code. Trie/Prefix Tree

• Problem: Given an array of numbers �, … , � , construct an efficient data structure which supports the following operations: • Add(�, �): Add � to the �-th cell (� ← � + �) • Max(�, �): Return max �, … , �

• Naïve approach - Use an array. • Add(�, �) in � 1 , Max(�, �) complexity is � � . • Worst case complexity for � queries is � �� . • Better: Use a segment tree! • Add(�, �), Max(�, �) are computed in � log � . • Worst case complexity for � queries is � � log � . Segment Tree

• Can be easily adapted to compute the sum/xor/max/min of all elements in a given segment. • Implementation: • Example is included in the attached .cpp file. • Refer to Wikipedia for more info. • The following blog post contains a brief introduction and examples: http://codeforces.com/blog/entry/18051 Fenwick tree

• Similar to a Segment Tree, but much quicker to implement. • Only supports the Sum(�, �) sums.

• For more info- • https://www.hackerearth.com/practice/data- structures/advanced-data-structures/fenwick-binary- indexed-trees/tutorial/ • https://www.topcoder.com/community/data- science/data-science-tutorials/binary-indexed-trees/ Union-Find

• Goal: Given a collection of items 1, … , � , construct an efficient data structure which supports the following operations: • Find(�): Determine which subset a particular element is in. By comparing the result of two Find operations, one can determine whether two elements are in the same subset. Union(�, �): Join two subsets into a single subset. • Union-Find is a part of the Kruskal MST algorithm. Union-Find

• Naïve implementation – Graph of items Do Union(0, 1) • Union(�, �) adds an edge � and �, Find(�) 1 2 3 determines subset ID using DFS. / • Worst case time complexity for O(n*n) 0 • Better solution - Disjoint- forests Do Union(1, 2) • Union(�, �), Find(�) in � log∗ � amortized – 1 3 almost constant! / \ 0 2 • Implementation: • Inverted trees for the disjoint-set forests are Do Union(2, 3) represented using parent arrays. 1 • Refer to Wikipedia and the attached .cpp file / | \ for more info. 0 2 3 General Tips

• Know your formula sheets! • Implementation can be tricky. • During a competition, make sure you understand the details before diving into implementation.

• Further reading: • Data Structures 1 for proofs and more variations: http://webcourse.cs.technion.ac.il/234218 • Wikipedia to give intuitive explanations and usually contains code snippets. • The Stanford ACM-ICPC Notebook contains optimized implementations for most graph algorithms: https://github.com/jaehyunp/stanfordacm