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. Trie/Prefix Tree
• 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 search tree 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 Segment 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-set 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 tries 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