 Open in App
Not now

# Final Exam | Google Kickstart 2021 Round D

• Difficulty Level : Hard
• Last Updated : 24 Feb, 2023

It’s time for the final exam in algorithms and data structures!

Edsger prepared N sets of problems. Each set consists of problems in an increasing difficulty sequence; the i-th set can be described by two integers Ai and Bi (Ai≤Bi), which denotes that this set contains problems with difficulties Ai, Ai+1…, Bi. Among all problems from all sets, it is guaranteed that no two problems have the same difficulty.

This semester Edsger has to test M students. He wants to test each student with exactly one problem from one of his sets. No two students can get the exact same problem, so when Edsger tests a student with some problem, he cannot use this problem anymore. Through countless lectures, exercises, and projects, Edsger has gauged student number j to have skill level Sj and wants to give that student a problem with difficulty Sj. Unfortunately, this is not always possible, as Edsger may have not prepared a problem of this difficulty, or he may have already asked this problem to some other student earlier. Therefore, Edsger will choose for the j-th student a problem of difficulty Pj, in a way that |Pj−Sj| is minimal and a question of difficulty Pj was not already given to any of the students before the j-th student. In case of ties, Edsger will always choose the easier problem. Note that the problem chosen for the j-th student may affect problems chosen for all the students tested later, so you have to process students in the same order as they appear in the input.

As keeping track of all the problems can be fairly complicated, can you help Edsger and determine which problems he should give to all of his students?

OR

Given an array problemRange of pairs having starting and ending values as a range of difficulty levels, and an array arr of size M indicating the difficulty level every student can attempt. The task is to assign a unique integer X from problemRange to every integer in array arr such that | arr[i] – X | is minimized. In case of a tie between two values closest to arr[i], a lesser difficulty value must be chosen. X values must be assigned to students in their order since the same value of X cannot be assigned to more than one student. Print the X value assigned to every student.

Example:

Input: N = 5, M = 4, arr = [14, 24, 24, 4], problemRange = [[1, 2], [6, 7], [9, 12], [24, 24], [41, 50]]
Output: 12 24 11 2
Explanation: values which can be assigned to the students are {1, 2}, {6, 7}, {9, 10, 11, 12}, {24}, {41, 42, 43, 44, 45, 46, 47, 48, 49, 50} 12 is assigned to first student who can attempt questions of difficulty level 14 as it is the closest to 14. 24 is closest to 24. Next student can also attempt question of 24 difficulty but 24 from the range is already chosen and the next closest is 11. 2 and 6 is closest to last student of difficulty 4, since 2 and 6 both are similarly close to 4, easier questions of difficulty level 2 is assigned.

Input: N = 1, M = 1, arr = , problemRange = [[42, 42]]
Output: 42

Approach: Given problem can be solved by following the steps below:

• Use a map to store the start of ranges as keys and end of ranges as values
• Iterate the array and for every element in it find its lower_bound in the map
• Two cases are possible: Lower_bound will return the iterator pointing to the key which will be equal to arr[i] or the key which is just greater than arr[i]
• let’s say the iterator provided by lower_bound be it and pre be an iterator just before it (pre will be equal to it when it=mp.begin())
• Either pre.first<=arr[i]<=pre.second or it.first<=arr[i]<=it.second will be true. arr[i] will lie in either the forward section or in the backward section of this range
• every time value is assigned to the arr[i] previous range is deleted from the map and a new range is added as shown in the image
• Either two new ranges are added or one new range is added as cases shown in the images below: Only one element is present in the range so it is removed and no new range is added arr[i] is equal to either one of the range The previous range is removed and two new ranges are added in the map

Below is the implementation of the above approach:

## C++

 `// C++ implementation for the above approach`   `#include `   `using` `namespace` `std;`   `void` `solve(``long` `long` `int` `N, ``long` `long` `int` `M,` `           ``vector >` `               ``problemRange,` `           ``vector<``long` `long` `int``> arr)` `{`   `    ``// Store the problem range in a map` `    ``map<``long` `long` `int``, ``long` `long` `int``> mp;`   `    ``for` `(``long` `long` `int` `i = 0; i < N; i++) {` `        ``long` `long` `int` `a, b;` `        ``a = problemRange[i].first;` `        ``b = problemRange[i].second;` `        ``mp[a] = b;` `    ``}`   `    ``vector<``long` `long` `int``> ans(M);`   `    ``for` `(``long` `long` `int` `i = 0; i < M; i++) {` `        ``auto` `it = mp.lower_bound(arr[i]);` `        ``auto` `pre = it;` `        ``if` `(it != mp.begin())` `            ``pre--;`   `        ``// If answer lies in a valid range` `        ``if` `(pre->first <= arr[i]` `            ``&& arr[i] <= pre->second) {` `            ``ans[i] = arr[i];` `            ``long` `long` `int` `st = pre->first,` `                          ``end = pre->second;` `            ``mp.erase(pre);` `            ``long` `long` `int` `left = arr[i] - 1,` `                          ``right = arr[i] + 1;` `            ``if` `(st <= left) {` `                ``mp[st] = left;` `            ``}` `            ``if` `(end >= right) {` `                ``mp[right] = end;` `            ``}` `        ``}`   `        ``// If answer is not in a valid range` `        ``else` `{` `            ``long` `long` `int` `op1 = pre->second,` `                          ``op2 = it->first;` `            ``if` `(``abs``(arr[i] - op1) <= ``abs``(arr[i] - op2)) {` `                ``ans[i] = op1;` `                ``long` `long` `int` `st = pre->first,` `                              ``end = op1 - 1;` `                ``mp.erase(pre);` `                ``if` `(st <= end)` `                    ``mp[st] = end;` `            ``}` `            ``else` `{` `                ``ans[i] = op2;` `                ``long` `long` `int` `st = it->first + 1,` `                              ``end = it->second;` `                ``mp.erase(it);` `                ``if` `(st <= end)` `                    ``mp[st] = end;` `            ``}` `        ``}` `    ``}` `    ``for` `(``auto` `it : ans)` `        ``cout << it << ``" "``;` `    ``cout << endl;` `}`   `// Driver code` `int` `main()` `{` `    ``long` `long` `int` `N, M;` `    ``N = 5;` `    ``M = 4;`   `    ``// Student difficulty level` `    ``vector<``long` `long` `int``> arr = { 14, 24, 24, 4 };`   `    ``vector >` `        ``problemRange = { { 1, 2 },` `                         ``{ 6, 7 },` `                         ``{ 9, 12 },` `                         ``{ 24, 24 },` `                         ``{ 41, 50 } };` `    ``solve(N, M, problemRange, arr);` `    ``return` `0;` `}`

## Java

 `import` `java.util.*;`   `public` `class` `Main {` `    ``public` `static` `void` `solve(``long` `N, ``long` `M,` `                             ``List> problemRange,` `                             ``List arr) {`   `        ``// Store the problem range in a map` `        ``TreeMap mp = ``new` `TreeMap<>();`   `        ``for` `(``long` `i = ``0``; i < N; i++) {` `            ``long` `a = problemRange.get((``int``)i).getKey();` `            ``long` `b = problemRange.get((``int``)i).getValue();` `            ``mp.put(a, b);` `        ``}`   `        ``List ans = ``new` `ArrayList<>();`   `        ``for` `(``long` `i = ``0``; i < M; i++) {` `            ``Map.Entry pre = mp.floorEntry(arr.get((``int``)i));` `            ``Map.Entry it = mp.ceilingEntry(arr.get((``int``)i));`   `            ``// If answer lies in a valid range` `            ``if` `(pre != ``null` `&& pre.getKey() <= arr.get((``int``)i)` `                    ``&& arr.get((``int``)i) <= pre.getValue()) {` `                ``ans.add(arr.get((``int``)i));` `                ``long` `st = pre.getKey();` `                ``long` `end = pre.getValue();` `                ``mp.remove(pre.getKey());` `                ``long` `left = arr.get((``int``)i) - ``1``;` `                ``long` `right = arr.get((``int``)i) + ``1``;` `                ``if` `(st <= left) {` `                    ``mp.put(st, left);` `                ``}` `                ``if` `(end >= right) {` `                    ``mp.put(right, end);` `                ``}` `            ``}`   `            ``// If answer is not in a valid range` `            ``else` `{` `                ``long` `op1 = pre != ``null` `? pre.getValue() : Long.MAX_VALUE;` `                ``long` `op2 = it != ``null` `? it.getKey() : Long.MAX_VALUE;` `                ``if` `(Math.abs(arr.get((``int``)i) - op1) <= Math.abs(arr.get((``int``)i) - op2)) {` `                    ``ans.add(op1);` `                    ``long` `st = pre.getKey();` `                    ``long` `end = op1 - ``1``;` `                    ``mp.remove(pre.getKey());` `                    ``if` `(st <= end) {` `                        ``mp.put(st, end);` `                    ``}` `                ``} ``else` `{` `                    ``ans.add(op2);` `                    ``long` `st = it.getKey() + ``1``;` `                    ``long` `end = it.getValue();` `                    ``mp.remove(it.getKey());` `                    ``if` `(st <= end) {` `                        ``mp.put(st, end);` `                    ``}` `                ``}` `            ``}` `        ``}` `        ``for` `(``long` `it : ans) {` `            ``System.out.print(it + ``" "``);` `        ``}` `        ``System.out.println();` `    ``}`   `public` `static` `void` `main(String[] args) {` `    ``long` `N = ``5``;` `    ``long` `M = ``4``;`   `    ``// Student difficulty level` `    ``List arr = Arrays.asList(14L, 24L, 24L, 4L);`   `    ``List> problemRange = ``new` `ArrayList<>();` `    ``problemRange.add(``new` `AbstractMap.SimpleEntry<>(1L, 2L));` `    ``problemRange.add(``new` `AbstractMap.SimpleEntry<>(6L, 7L));` `    ``problemRange.add(``new` `AbstractMap.SimpleEntry<>(9L, 12L));` `    ``problemRange.add(``new` `AbstractMap.SimpleEntry<>(24L, 24L));` `    ``problemRange.add(``new` `AbstractMap.SimpleEntry<>(41L, 50L));`   `    ``solve(N, M, problemRange, arr);` `}` `}`

## Python3

 `# Python3 program to implement the approach` `def` `solve(N, M, problemRange, arr):` `    ``# Store the problem range in a dictionary` `    ``mp ``=` `{}` `    ``for` `i ``in` `range``(N):` `        ``a, b ``=` `problemRange[i]` `        ``mp[a] ``=` `b`   `    ``ans ``=` `[``0``] ``*` `M`   `    ``for` `i ``in` `range``(M):` `        ``it ``=` `next``((k ``for` `k ``in` `sorted``(mp.keys()) ``if` `k >``=` `arr[i]), ``None``)` `        ``if` `it ``is` `None``:` `            ``it ``=` `sorted``(mp.keys())[``-``1``]`   `        ``pre ``=` `None` `        ``if` `it !``=` `sorted``(mp.keys())[``0``]:` `            ``pre ``=` `sorted``(mp.keys())[``sorted``(mp.keys()).index(it) ``-` `1``]`   `        ``# If answer lies in a valid range` `        ``if` `pre ``is` `not` `None` `and` `pre <``=` `arr[i] <``=` `mp[pre]:` `            ``ans[i] ``=` `arr[i]` `            ``st, end ``=` `pre, mp[pre]` `            ``del` `mp[pre]` `            ``left, right ``=` `arr[i] ``-` `1``, arr[i] ``+` `1` `            ``if` `st <``=` `left:` `                ``mp[st] ``=` `left` `            ``if` `end >``=` `right:` `                ``mp[right] ``=` `end`   `        ``# If answer is not in a valid range` `        ``else``:` `            ``op1 ``=` `mp[pre] ``if` `pre ``is` `not` `None` `else` `None` `            ``op2 ``=` `mp[it]` `            ``if` `op1 ``is` `not` `None` `and` `abs``(arr[i] ``-` `op1) <``=` `abs``(arr[i] ``-` `op2):` `                ``ans[i] ``=` `op1` `                ``st, end ``=` `pre, op1 ``-` `1` `                ``del` `mp[pre]` `                ``if` `st <``=` `end:` `                    ``mp[st] ``=` `end` `            ``else``:` `                ``ans[i] ``=` `op2` `                ``st, end ``=` `it ``+` `1``, mp[it]` `                ``del` `mp[it]` `                ``if` `st <``=` `end:` `                    ``mp[st] ``=` `end` `    `  `    ``# Displaying the answer` `    ``for` `it ``in` `ans:` `        ``print``(it, end``=``' '``)` `    ``print``()`   `# Driver code` `if` `__name__ ``=``=` `"__main__"``:` `    ``N, M ``=` `5``, ``4`   `    ``# Student difficulty level` `    ``arr ``=` `[``14``, ``24``, ``24``, ``4``]`   `    ``problemRange ``=` `[(``1``, ``2``), (``6``, ``7``), (``9``, ``12``), (``24``, ``24``), (``41``, ``50``)]` `    `  `    ``# Function call` `    ``solve(N, M, problemRange, arr)`

## C#

 `// Import necessary packages` `using` `System;` `using` `System.Collections.Generic;`   `class` `GFG {` `  ``public` `static` `void` `    ``Solve(``long` `N, ``long` `M,` `          ``List > problemRange,` `          ``List<``long``> arr)` `  ``{` `    ``// Store the problem range in a sorted dictionary` `    ``var` `mp = ``new` `SortedDictionary<``long``, ``long``>();` `    ``for` `(``long` `i = 0; i < N; i++) {` `      ``long` `a = problemRange[(``int``)i].Key;` `      ``long` `b = problemRange[(``int``)i].Value;` `      ``mp[a] = b;` `    ``}`   `    ``List<``long``> ans = ``new` `List<``long``>();`   `    ``for` `(``long` `i = 0; i < M; i++) {` `      ``long` `key = arr[(``int``)i];`   `      ``// Find the floor and ceiling entries` `      ``KeyValuePair<``long``, ``long``> pre, it;` `      ``bool` `hasPre = ``false``, hasIt = ``false``;` `      ``pre = ``new` `KeyValuePair<``long``, ``long``>(` `        ``long``.MinValue, ``long``.MinValue);` `      ``it = ``new` `KeyValuePair<``long``, ``long``>(` `        ``long``.MaxValue, ``long``.MaxValue);` `      ``foreach``(KeyValuePair<``long``, ``long``> kvp ``in` `mp)` `      ``{` `        ``if` `(kvp.Key <= key && kvp.Key >= pre.Key) {` `          ``pre = kvp;` `          ``hasPre = ``true``;` `        ``}` `        ``if` `(kvp.Key >= key && kvp.Key <= it.Key) {` `          ``it = kvp;` `          ``hasIt = ``true``;` `        ``}` `      ``}`   `      ``// If answer lies in a valid range` `      ``if` `(hasPre && key >= pre.Key` `          ``&& key <= pre.Value) {` `        ``ans.Add(key);` `        ``long` `st = pre.Key;` `        ``long` `end = pre.Value;` `        ``mp.Remove(pre.Key);` `        ``long` `left = key - 1;` `        ``long` `right = key + 1;` `        ``if` `(st <= left) {` `          ``mp[st] = left;` `        ``}` `        ``if` `(end >= right) {` `          ``mp[right] = end;` `        ``}` `      ``}`   `      ``// If answer is not in a valid range` `      ``else` `{` `        ``long` `op1` `          ``= hasPre ? pre.Value : ``long``.MaxValue;` `        ``long` `op2 = hasIt ? it.Key : ``long``.MaxValue;` `        ``if` `(Math.Abs(key - op1)` `            ``<= Math.Abs(key - op2)) {` `          ``ans.Add(op1);` `          ``long` `st = pre.Key;` `          ``long` `end = op1 - 1;` `          ``mp.Remove(pre.Key);` `          ``if` `(st <= end) {` `            ``mp[st] = end;` `          ``}` `        ``}` `        ``else` `{` `          ``ans.Add(op2);` `          ``long` `st = it.Key + 1;` `          ``long` `end = it.Value;` `          ``mp.Remove(it.Key);` `          ``if` `(st <= end) {` `            ``mp[st] = end;` `          ``}` `        ``}` `      ``}` `    ``}`   `    ``foreach``(``long` `it ``in` `ans) { Console.Write(it + ``" "``); }` `    ``Console.WriteLine();` `  ``}`   `  ``public` `static` `void` `Main(``string``[] args)` `  ``{` `    ``long` `N = 5;` `    ``long` `M = 4;`   `    ``// Student difficulty level` `    ``List<``long``> arr = ``new` `List<``long``>{ 14, 24, 24, 4 };`   `    ``List > problemRange` `      ``= ``new` `List >();` `    ``problemRange.Add(` `      ``new` `KeyValuePair<``long``, ``long``>(1, 2));` `    ``problemRange.Add(` `      ``new` `KeyValuePair<``long``, ``long``>(6, 7));` `    ``problemRange.Add(` `      ``new` `KeyValuePair<``long``, ``long``>(9, 12));` `    ``problemRange.Add(` `      ``new` `KeyValuePair<``long``, ``long``>(24, 24));` `    ``problemRange.Add(` `      ``new` `KeyValuePair<``long``, ``long``>(41, 50));`   `    ``// Function call` `    ``Solve(N, M, problemRange, arr);` `  ``}` `}`   `// This code is contributed by phasing17`

## Javascript

 `// JS implementation of the approach` `function` `Solve(N, M, problemRange, arr) ` `{`   `    ``// Store the problem range in a sorted dictionary` `    ``let mp = ``new` `Map();` `    ``for` `(let i = 0; i < N; i++) {` `        ``let a = problemRange[i];` `        ``let b = problemRange[i];` `        ``mp.set(BigInt(a), BigInt(b));` `    ``}`   `    ``let ans = [];`   `    ``for` `(let i = 0; i < M; i++) {` `        ``let key = BigInt(arr[i]);`   `        ``// Find the floor and ceiling entries` `        ``let pre = [BigInt(Number.MIN_SAFE_INTEGER), BigInt(Number.MIN_SAFE_INTEGER)];` `        ``let it = [BigInt(Number.MAX_SAFE_INTEGER), BigInt(Number.MAX_SAFE_INTEGER)];` `        ``let hasPre = ``false``,` `            ``hasIt = ``false``;` `        ``for` `(let kvp of mp) {` `            ``if` `(kvp <= key && kvp >= pre) {` `                ``pre = kvp;` `                ``hasPre = ``true``;` `            ``}` `            ``if` `(kvp >= key && kvp <= it) {` `                ``it = kvp;` `                ``hasIt = ``true``;` `            ``}` `        ``}`   `        ``// If answer lies in a valid range` `        ``if` `(hasPre && key >= pre && key <= pre) {` `            ``ans.push(key);` `            ``let st = pre;` `            ``let end = pre;` `            ``mp.``delete``(pre);` `            ``let left = key - BigInt(1);` `            ``let right = key + BigInt(1);` `            ``if` `(st <= left) {` `                ``mp.set(st, left);` `            ``}` `            ``if` `(end >= right) {` `                ``mp.set(right, end);` `            ``}` `        ``}`   `        ``// If answer is not in a valid range` `        ``else` `{` `            ``let op1 = hasPre ? pre : BigInt(Number.MAX_SAFE_INTEGER);` `            ``let op2 = hasIt ? it : BigInt(Number.MAX_SAFE_INTEGER);` `        `  `        ``// Defining abs method for BigInt` `        ``const abs = (n) => (n < 0n) ? -n : n;`   `        ``if` `(abs(key - op1) <= abs(key - op2)) {` `            ``ans.push(op1);` `            ``let st = pre;` `            ``let end = op1 - BigInt(1);` `            ``mp.``delete``(pre);` `            ``if` `(st <= end) {` `                ``mp.set(st, end);` `            ``}` `        ``} ``else` `{` `            ``ans.push(op2);` `            ``let st = it + BigInt(1);` `            ``let end = it;` `            ``mp.``delete``(it);` `            ``if` `(st <= end) {` `                ``mp.set(st, end);` `            ``}` `        ``}` `    ``}` `}`   `for` `(let it of ans) {` `    ``process.stdout.write(it + ``" "``);` `}` `process.stdout.write(``"\n"``);` `}`   `let N = BigInt(5);` `let M = BigInt(4);`   `// Student difficulty level` `let arr = [BigInt(14), BigInt(24), BigInt(24), BigInt(4)];`   `let problemRange = [` `    ``[BigInt(1), BigInt(2)],` `    ``[BigInt(6), BigInt(7)],` `    ``[BigInt(9), BigInt(12)],` `    ``[BigInt(24), BigInt(24)],` `    ``[BigInt(41), BigInt(50)]` `];`   `// Function call` `Solve(N, M, problemRange, arr);`

Output

`12 24 11 2 `

Time complexity: MLog(N)
Auxiliary Space: O(N)

My Personal Notes arrow_drop_up
Related Articles