Here is the link to the contest. The problems are from Codeforces problemset.
A. Ascend
Let's iterate through the given array and store the length of the current increasing subarray in the variable $$$curLen$$$. If the current element is more than the previous we need to increase $$$curLen$$$ by one. Otherwise, the current number is a start of a new increasing subarray, so we need to restart $$$curLen$$$ with $$$1$$$. We keep track of the maximum after considering every number.
import sys
input = lambda: sys.stdin.readline().rstrip()
n = int(input())
a = list(map(int, input().split()))
max_len = 1
cur_len = 1
for idx in range(1, n):
if a[idx - 1] >= a[idx]:
cur_len = 0
cur_len += 1
max_len = max(max_len, cur_len)
print(max_len)
B. String Fusion
C. Prefix-Free Words
To solve this problem efficiently, we can sort the given input array of word length in ascending order while keeping track of their original indices.It helps in generating the smallest possible lexicographical strings by starting with the shortest strings. Using a $$$Trie$$$ data structure, we efficiently generate unique binary strings for each length, which are not a prefix of other words. For each length, starting from the smallest, we can build a binary string by traversing the $$$Trie$$$. If a binary string of the required length cannot be uniquely formed (i.e., both possible extensions lead to existing valid prefixs), we will return $$$NO$$$. If successful, we can store the binary string and update the $$$Trie$$$ to reflect the newly added string. After forming a binary string, we have to backtrack to update the $$$is_end$$$ flags appropriately to ensure that we correctly mark nodes as end nodes when there are no further possible paths (all childrens are occupied).
Time Complexity: $$$O(NlogN + N * M)$$$ time. N is input array length and M denotes the maximum word length
Space Complexity: $$$O(N * M)$$$
class TrieNode:
def __init__(self):
self.ch = [None, None]
self.is_end = False
class Trie:
def __init__(self):
self.root = TrieNode()
def insert(self, length):
stack, trie = [], self.root
word = []
# finding a unique word representation with the given length
for i in range(length):
stack.append(trie)
if trie.ch[0] is None or not trie.ch[0].is_end:
if trie.ch[0] is None:
trie.ch[0] = TrieNode()
trie = trie.ch[0]
word.append('0')
elif trie.ch[1] is None or not trie.ch[1].is_end:
if trie.ch[1] is None:
trie.ch[1] = TrieNode()
trie = trie.ch[1]
word.append('1')
else:
return False
trie.is_end = True
# backtrcking to update the is_end of the nodes if they don't have unoccopied child for the word represetnation
while stack and stack[-1].ch[1] and stack[-1].ch[1].is_end:
prev = stack.pop()
prev.is_end = True
return ''.join(word)
def main():
n = int(input())
nums = sorted(zip(map(int, input().split()), range(n)))
trie = Trie()
words = [''] * n
for num, indx in nums:
word = trie.insert(num)
if not word:
print('NO')
return
words[indx] = word
print('YES')
for word in words:
print(word)
if __name__ == '__main__':
main()
D. BitPleasure Maximization
How can we find the best possible match for the XOR of some number from an array using a Trie?.
Can We use the same concept for prefix and suffix?
For this problem, we will use the Trie data structure. Let's start by calculating the prefix of the array. For $$$(0 \leq i \leq n)$$$, let $$$pref[0] = 0$$$. After calculating $$$prefix[i]$$$, we should add $$$prefix[i]$$$ to the Trie. Then, we can easily calculate the best possible match for the XOR of the new suffix that starts from $$$n$$$ and ends at $$$i + 1$$$. In this case, we are guaranteed that the prefix and suffix do not intersect.
import sys
class Node:
def __init__(self):
self.children = [None, None]
class Trie:
def __init__(self, val):
self.root = Node()
self.bit_len = val
def insert(self, num):
cur = self.root
for i in range(self.bit_len, -1, -1):
bit = 1 if num & (1 << i)else 0
if cur.children[bit] is None:
cur.children[bit] = Node()
cur = cur.children[bit]
def findMax(self, num):
cur = self.root
max_num = 0
for i in range(self.bit_len, -1, -1):
bit = 1 if num & (1 << i) else 0
if cur.children[1 - bit] is not None:
max_num = max_num | (1 << i)
cur = cur.children[1 - bit]
else:
cur = cur.children[bit]
return max_num
n = int(sys.stdin.readline().strip())
nums = list(map(int, sys.stdin.readline().strip().split()))
trie = Trie(len(bin(max(nums))))
tot_pref = 0
nums = [0] + nums
for num in nums:
tot_pref ^= num
cur_pref = 0
ans = 0
for num in nums:
cur_pref ^= num
trie.insert(cur_pref)
ans = max(ans, trie.findMax(cur_pref ^ tot_pref))
print(ans)