Skip to main content

Placements '24: Assessments [Part 1]

Image of the author

Eshaan Aggarwal @EshaanAgg

Here is a brief of some online assessments (patterns, questions & tips) that I either personally gave or heard about from my peers during the season of 2024.

In addition to reading about the questions from here, please do search for the companies on Leetcode Discuss or Job Overflow. Sometimes people even post about OA questions in Codeforces blogs, so spending a bit of time searching for such questions (from past years or from different campuses) can help you gain an unexpected edge!

PS. I have tried to add the solutions of the problems from the time that I had solved them to as many problems as possible, but they may not be necessarily correct. Please raise an issue here if you find any mistakes, either in the solutions or in the content of the blog!


GreyOrange

Coding Questions


Squarepoint Capital

Quant Desk Analyst

Two coding questions were asked which were same for all the students were asked.

  1. A simple implementation of two pointers was to be done, which was described in the question itself. Brute approach needed. LC Easy level.

  2. You are given a matrix of size 100X100100 X 100 with values between 11 and 5050. In one operation, you can choose any one element, and delete all the elements with the same value in the row and column of the picked element (along with the element itself). Give the minimum number of operations to delete all the elements.

    Spoiler

    You can read about question 2 here. The question actually turns out to be NP Complete, and thus the best you can do is brute force and try all orderings. In the OA to pass the questions, you had to use the (incorrect) greedy approach, where you would always choose the element whose deletion would result in the maximum number of deletions. To solve it in actual constraints, you can try this on Codeforces.

  3. You are given an array of size nn. You can change any number in the array to any value, and the cost of changing the same is absolute difference of new number and old number. Find the minimum cost to make the array either non-increasing or non-decreasing.

    Example:

    Input: 1 3 5 4 7
    Output: 1
    Explanation: It can be changed to 1 3 5 5 7 (cost to change 4 to 5 is 1)

    Spoiler

    You can first try solving this similar question and then try to modify the solution to fit the constraints of the question.

  4. You are given two numbers minValminVal and maxValmaxVal and an array arrarr. You need to calculate the number of contigous subarrays with minimum value as minValminVal and maximum value as maxValmaxVal. Length of array is upto was 10510^5.

    This problem was a restatement of a problem on Leetcode.

  5. You are given an array arrarr. You need to remove elements from the array until array gets empty. You can remove either first or last element from the same, with the objective of maximizing the score. Score is calculated in this way:

    • Add the array sum to the score if the operation serial number was odd, and then remove an element from the array.
    • Subtract the array sum from the score if the operation serial number was even and then remove the element from the array.

    The length of the array was upto 20002000.

    Solution

    We can use a 2D2D DP to solve this problem. Let dp[i][j]dp[i][j] denote the maximum score that can be obtained by when the first ii and the last jj elements have been removed. We can then define the transition as:

    1
    int count(int i, int j, vector<int> &arr, vector<int> &pre, vector<vector<int>> &dp) {
    2
    int n = arr.size();
    3
    4
    if (i + j == n) return 0;
    5
    if (dp[i][j] != -1) return dp[i][j];
    6
    7
    int turn = (i + j + 1) % 2;
    8
    int stIdx = i, endIdx = n - j - 1;
    9
    10
    int sum = pre[endIdx] - (stIdx > 0 ? pre[stIdx - 1] : 0);
    11
    if (turn % 2 == 0) sum = -sum;
    12
    13
    dp[i][j] = max(sum + count(i + 1, j, arr, pre, dp), sum + count(i, j + 1, arr, pre, dp));
    14
    return dp[i][j];
    15
    }
    16
    17
    int solve(vector<int> &arr) {
    18
    int n = arr.size();
    19
    vector<int> pre(n);
    20
    for (int i = 0; i < n; ++i) {
    21
    pre[i] = arr[i] + (i > 0 ? pre[i - 1] : 0);
    22
    }
    23
    24
    vector<vector<int>> dp(n, vector<int>(n, -1));
    25
    return count(0, 0, arr, pre, dp);
    26
    }

Software Developer

Everyone had different questions, but most of them were LC Easy or Medium. The questions often had vague wording so a lot of hit and trial was required to pass the test cases. Questions from the previous years were repeated. Only 2 programming questions were present for one student.

  1. You are given a list of words and a search word. For each prefix in the search word (let’s say XX), you need to find at max 3 lexicographically smallest words from the dictionary that have the same prefix X.

    • Number of dictionary words 105\leq 10^5
    • Length of dictionary word: 104\leq 10^4
    • Sum(Length of all dictionary words) 105\leq 10^5
    • Length of search word: 103\leq 10^3

    You can try it out here.

  2. A question involving generating unique usernames for all the users on a platform was asked. Only basic string processing was needed, but having vague test descriptions made it difficult to pass the test cases. I had used the debug console to print out the testcases and then tried to guess the output the testcases were expecting. Nasty tricks like trailing whitespaces and wierd ASCII characters were used to make the testcases fail, so you had to be very careful with the output.

Infrastructure Engineer

The test had two sections, one based on Python and two based on Linux.

Linux Section

Remote machines were provided to us, and we had to write the Bash scripts to perform the following tasks. Having access to the server allowed to experiment with the commands and test the scripts before submitting them. The evaluation would happen after the contest, where the script would be used on a similar but new server, and check if all the objectives were met.

  1. You need to run a nginx Docker container and bind it’s default port to the server’s port 80008000.

  2. You were given a file with the first names and the last name of some users. You need to do the following:

    • Read the file
    • Create a new user for each user in the file with the username as F_LastName where F is the first letter of the first name and LastName is the last name.
    • Assign all the users to a group named users.
    • Ensure that the users are asked to change their password on the first login.
    John Doe
    Jane Doe
    John Smith

Python Section

A mock API endpoint was provided, to which we had to make an API call to fetch the data. The response needed to be manipulated and some basic processing of the data items was needed. The response was paginated, so we had to make multiple requests to get all the data. Only basic working experience with Python, and the requests library was needed for this section.


AQR Capital

The coding questions are relatively easy as compared to other companies, but the MCQs are a bit tricky and time-consuming. I would highly recommend practicing MCQs from GeeksforGeeks and other platforms before giving the test. SQL is one of the most important topics for AQR, so make sure you are well-versed with it.

Also, AQR is known for having wierd (more often that not) atleast one wrong test-case in their OAs, so if you finish early and are stuck on the last test-case, it might be better to skip it! In both my intern as well as placement exams, one test-case was wrong in one of the questions. AQR also does not run the same number of test-cases for everyone, so it’s possible that you might get a different number of test-cases than your friend.

PYQs

  1. There is a river from point 00 to LL. You need to cross the river by stepping on stones. There are nn stones present in the river at the points arr[i]arr[i]. During your journey, if the max jump that you make is kk, and the number of jumps that you make is xx, then the cost associated with the journey is equal to k2+cxk^2 + cx where cc is fixed constant. Calculate the minimum cost to cross the river.

    • arr[i]arr[i], L109L \leq 10^9
    • n1000n \leq 1000
    • c105c \leq 10^5
  2. Given a DAG with atmost 10001000 nodes, print the two largest strongly connected components in the graph. Also print the shortest path between the two components. If there are multiple shortest paths, you need to print the path that with “extreme” vertices for the component. (Proper clarifications on the meaning of the “extreme” vertices was not given)

  3. MCQ questions based on the following topics were given:

    • Marker & Functional Interfaces in Java
    • Type of Relationships: IS, HAS & USES

Online Assessment

  1. MCQs (18) and Fill-in-the-blanks (2) were asked. The primary topics of the same were:

    • SQL
    • Java
      • Assertions & Exceptions
      • Break & Skip Statements
      • Stream & ParallelStream in Java
      • Static members and methods
    • Design Principles
      • Single Responsibility Principle (SRP)
      • Open-Closed Principle (OCP)
      • Liskov Substitution Principle (LSP)
      • Interface Segregation Principle (ISP)
    • OOPS
      • Inheritance
      • Polymorphism
      • Encapsulation
      • Abstraction
  2. You are given an an array of scores arr[i]arr[i] of nn students. You need to arrange them such that the highest score is the middle, the second highest score is to the left of the highest score, the third highest score is to the right of the highest score, the fourth highest score is to the left of the second highest score, and so on.

    Example:

    Input: [1, 2, 3, 4, 5]
    Output: [2, 4, 5, 3, 1]
  3. The question revolved around calculating the sum of the nodes of a binary tree which had exactly two children. The tree nodes were given in a non-convental way (as a string of L and R characters denoting the path that you need to take to reach the node from the root).


Graviton Research Capital

Graviton is known for it’s subjective tests. It did not visit our campus, but I had a few friends who gave the test. Each test had 3-4 questions, and partial & step marking was present.

PYQs

Software Developer

  1. Modify the code snippet to remove all branches (if statements):

    int m = 1 << 15;
    int data[m];
    for (int i = 0; i < m; i++)
    data[i] = rand() % 256;
    int sum = 0;
    for (int i = 0; i < m; i++)
    if (data[i] >= 128)
    sum += data[i];
    cout << sum << endl;

    Solution

    We need to add the numbers in the range 128128 to 255255, all of which have their 77th bit always set. Thus if a number’s 77th bit is set, we can add it to the result, otherwise we can ignore it. We can use the following code snippet to achieve the same:

    for (int i = 0; i < m; i++) {
    int toAdd = (data[i] >> 7) & 1;
    sum += toAdd * data[i];
    }
  2. There are nn datapoints given, each with coordinates (x,y)(x, y). Each data point can spread upto a max distance of rr units. What is the minimum value of rr so that all the datapoints can talk to each other? (Two datapoints can talk to each other if the distance between them is less than or equal to rr. Datapoints can talk in a chain, i.e. if AA can talk to BB and BB can talk to CC, then AA can talk to CC)

    Constraints:

    • n1000n \leq 1000
    • xx, y25000y \leq 25000
    Solution

    We observe the fact that if the datapoints can talk to each other at a distance of rr, then:

    • The graph formed by the datapoints is a single connected component.
    • All these datapoints would be able to be communicate with each other for any r>rr' > r as well.

    Thus using these two facts, we can use binary search to find the minimum value of rr for which the graph is a single connected component. For each value of rr, we can use loop over all the pairs of datapoints, connect them if the distance between them is less than or equal to rr and then check if the graph is a single connected component or not (using DFS, BFS or Union Find).

    The overall complexity of the solution would be O(n2logMAX(x,y))O(n^2 \log MAX(x,y)) which is feasible for the given constraints.

  3. There are nn players in a game, each with a certain number of gold chips denoted by arr[i]arr[i]. The maximum number of gold chips that a player can have is denoted by capacity[i]capacity[i]. You are the player at index 00 and thus initially have arr[0]arr[0] gold chips. You can give your gold chips to other players to improve your rank. If a player has more gold chips than its capacity, then that player disqualifies and your rank improves. Find an algorithm to get your best rank.

    Solution

    We can use a combination of greedy & brute force approach to solve this problem. Let’s say we have decided that we want to eliminate some people by giivng them our gold chips. It would always be ideal for us to give our coins to the player with the lowest capacity[i]arr[i]capacity[i] - arr[i] value. This exchange would increase our rank by 11 due to elimination, but also might decrease our rank by xx due to now more player having more coins than me.

    We can efficiently simulate all the possible number of coins that we can spend by maintaing two priority queues:

    • One to keep track of the players that I can eliminate, ordered by the difference of their capacity and current coins.
    • One to keep track of players who have coins lesser than me.

    We can then simulate the process of giving coins to the players and updating the ranks. The overall complexity of the solution would be O(nlogn)O(n \log n).

    1
    // Returns the rank as the number of people having lesser coins than me
    2
    int bestRank(vector<int> arr, vector<int> cap) {
    3
    4
    priority_queue<pair<int, int>> lesserThanMe; // Max Heap -> <coins, index>
    5
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> canEliminate; // Min Heap -> <capacity - coins + 1, index>
    6
    7
    for (int i = 1; i < arr.size(); ++i) {
    8
    if (arr[i] < arr[0])
    9
    lesserThanMe.push({arr[i], i});
    10
    else
    11
    canEliminate.push({cap[i] - arr[i] + 1, i});
    12
    }
    13
    14
    int ans = lesserThanMe.size();
    15
    16
    // Loop while I can eliminate some players
    17
    while (!canEliminate.empty() && arr[0] >= canEliminate.top().first) {
    18
    auto [diff, index] = canEliminate.top();
    19
    canEliminate.pop();
    20
    21
    arr[0] -= diff; // Update my coins
    22
    23
    // Add all the newly eligible players to the canEliminate heap
    24
    while (!lesserThanMe.empty() && arr[0] < lesserThanMe.top().first) {
    25
    auto [coins, i] = lesserThanMe.top();
    26
    lesserThanMe.pop();
    27
    canEliminate.push({cap[i] - arr[i] + 1, i});
    28
    }
    29
    30
    ans = min(ans, (int)lesserThanMe.size());
    31
    }
    32
    33
    return ans;
    34
    }

    This code still requires some better handling around ties and how to determine ranks if two people have the same number of coins, but the general idea is the same.

  4. Build a transaction function that may run parallely on multiple cores with the signature:

    bool transaction(Entity &sender, Entity &receiver, int amount);

    Solution

    The question is not very clear, but the main idea is to ensure that the transaction function is thread-safe. You can use locks to ensure that only one thread can access the function at a time, and we can assume that these locks are available on the Entity class itself. A simple implementation would look like:

    1
    #include <iostream>
    2
    #include <mutex>
    3
    #include <thread>
    4
    #include <vector>
    5
    6
    class Entity {
    7
    public:
    8
    Entity(int id, int initial_balance) : id(id), balance(initial_balance) {}
    9
    10
    int getBalance() const { ... }
    11
    void updateBalance(int amount) { ... } // Not thread-safe
    12
    int getId() const { ... }
    13
    14
    private:
    15
    int id;
    16
    int balance;
    17
    std::mutex mtx;
    18
    19
    public:
    20
    // Thread-safe transfer method (synchronization within entity)
    21
    bool transferTo(Entity &receiver, int amount) {
    22
    std::scoped_lock lock(mtx, receiver.mtx);
    23
    24
    if (balance < amount) {
    25
    return false;
    26
    }
    27
    28
    updateBalance(-amount);
    29
    receiver.updateBalance(amount);
    30
    return true;
    31
    }
    32
    };
    33
    34
    bool transaction(Entity &sender, Entity &receiver, int amount) {
    35
    return sender.transferTo(receiver, amount);
    36
    }
    37
    38
    int main() {
    39
    Entity alice(1, 1000);
    40
    Entity bob(2, 500);
    41
    42
    std::vector<std::thread> threads;
    43
    44
    // Launch multiple transactions in parallel
    45
    for (int i = 0; i < 5; ++i) {
    46
    threads.emplace_back([&]() {
    47
    int amount = rand() % 150;
    48
    if (transaction(alice, bob, amount)) {
    49
    std::cout << "Success!\n";
    50
    } else {
    51
    std::cout << "Failed!\n";
    52
    }
    53
    });
    54
    }
    55
    56
    // Wait for all threads to finish
    57
    for (auto &t : threads) {
    58
    t.join();
    59
    }
    60
    61
    std::cout << "Final balance of Alice: " << alice.getBalance() << "\n";
    62
    std::cout << "Final balance of Bob: " << bob.getBalance() << "\n";
    63
    64
    return 0;
    65
    }

    This article can be helpful to understand the concept of mutexes in C++ if you haven’t seem them before. Scoped locks are a neat C++ 17 feature that can be used to lock multiple mutexes at once without the risk of deadlocks.

  5. In a 3232 bit machine, we subdivide the virtual address into 4 segments as follows:

    | 10 bit | 8 bit | 6 bit | 8 bit |

    We use a 33 level page table, such that the first 1010 bit is for the first level and so on. Assuming the size of a page table entry as 22 bytes, answer these questions:

    • What is the page size in such a system?
    • What is the size of a page table for a process that has 256K256K of memory starting at address 00?
  6. You are tasked with architecting the CPU pipeline for a hypothetical high-performance processor that must meet the following specifications:

    • A deeply pipelined architecture consisting of 1515 stages.

    • The implementation of dynamic branch prediction (e.g., leveraging a hybrid predictor combining both global and local history).

      • Describe how you would structure the pipeline stages, focusing on optimizing and balancing the stages for instruction fetch, decode, execution, memory access, and write-back.
      • What challenges do you anticipate in managing a deep pipeline of this nature? Propose techniques and strategies to address these challenges effectively.
      • Design a branch prediction mechanism suitable for this architecture, discussing how your design would balance prediction accuracy and the associated performance overhead.
  7. Given an array aa of nn integers, we have to split the array into continuous non-empty subarrays. Let’s say there are kk subarrays and let the ithi^{th} subarray be from [l(i)tor(i)][l(i) to r(i)] — both inclusive. Hence a split of the array will satisfy k1k \geq 1, [l(i)r(i)][l(i) \leq r(i)] for 1ik1 \leq i \leq k, l(1)=1l(1) = 1, r(k)=nr(k) = n, r(i)+1=l(i+1)r(i) + 1 = l(i+1) for 1ik1 \leq i \leq k.

    Each subarray has a value assigned to it. For a subarray from ll to rr, the value val(l,r)val(l, r) is calculated as follows:

    • First calculate:
    • sum=a[l]+a[l+1]+a[l+2]+...+a[r1]+a[r]sum = a[l] + a[l+1] + a[l+2] + ... + a[r-1] + a[r]
    • size=rl+1size = r - l + 1
    • Then val(l,r)val(l, r) is:
    • 00, if sum=0sum = 0
    • +size+size, if sum>0sum > 0
    • size-size, if sum<0sum < 0

    The value of a split of the array is the sum of values of all the subarrays of the split. You are requested to find the maximum value of a split possible (over all possible splits of the array).

    Constraints:

    • 1n51051 \leq n \leq 5*10^5
    • 109a[i]109-10^9 \leq a[i] \leq 10^9
  8. You are currently trapped in a maze with nn rooms, which are connected by bridges. Each bridge connects two rooms (u,v)(u, v) and has a maximum weight capacity ww. It breaks if the load exceeds ww. Bridges can be used to travel in both directions and any number of times (as long as the bridge can hold your weight).

    There is one magic fruit in each room, and to escape the maze, you have to eat all the magic fruits (an exit portal opens in the room where you finish eating the last fruit). Eating the magic fruit in room ii increases your weight by a[i]a[i].

    You are currently in room number 11. You realize that with your current weight it might not be possible to escape the maze. So you wonder what is the maximum starting weight with which it is possible to eat all the magic fruits (without breaking a bridge and getting trapped in the maze) to escape.

    You can assume that the maze is designed in such a way that you can escape it with some positive starting weight. It is not mandatory to eat the magic fruit the first time you visit a room, and each room can be visited any number of times.

    Constraints:

    • 1n51051 \leq n \leq 5*10^5
    • 109a[i]109-10^9 \leq a[i] \leq 10^9
    • 1m51051 \leq m \leq 5*10^5
    • 1u[i],v[i]n1 \leq u[i], v[i] \leq n
    • 1w[i]1091 \leq w[i] \leq 10^9

Quant Analyst

  1. There is a city with different chambers. Each chamber has at least 33 light bulbs. The total number of light bulbs is even. There is a switch between any 22 light bulbs (both the light bulbs can be in the same chamber or different chambers). Assume some initial configuration of the light bulbs. Is it possible to have a sequence of changes in the switches such that each chamber has both light bulbs (on and off), irrespective of the initial state?

  2. There is a lift in a multi-level building. The probability of the lift going up is 0.20.2, going down is 0.30.3 and staying still is 0.50.5. At floor 00, the probability of going up is 0.20.2 and staying is 0.80.8. Assume infinite floors in the building. What is the proportion of time you are going to stay at level 00?

  3. There is a sequence of cards with some facing down and some facing up. If there are nn cards facing up, then you will flip the nthn^{th} card from the left. You keep doing this until all the cards are facing down. Let the total number of cards be PP.

    • Is it always possible to bring all the cards facing down irrespective of the initial positioning?
    • If it is possible to face all cards down, what is the expected length of sequence of moves?
  4. There is a uniform distribution in the range [0,1][0, 1]. Ram and Shyam get 22 numbers from this range at random. Both only know about the number that they have received. The player having a higher value wins. Ram has a chance to redraw another number at random from the distribution. Assuming that both the players play optimally, how many times will Ram choose to redraw?

  5. Google wants to pick a new CEO. Mr. Pichai has a list of candidates he can recommend. He has NN people on the list, each of which has a probablity p[i]p[i] of being selected as the CEO. You need to help Mr. Pichai maximize the probablity of exactly one candidate getting selected. You need to provide a solution for any NN and p[i]p[i].

  6. You are given a tree TT containing NN nodes and N1N-1 edges. Assume that each node of this tree is coloured either black or white independently with a probability of 0.50.5. We define GG as the smallest connected subgraph of TT that contains all the black nodes. What is the expected number of white nodes in GG? (NN is between 22 and 10510^5)

  7. There is tree of nn vertices, labelled 11 to nn. For every tree, you can assign it a sequence aa as follows:

    • Let the sequence be empty intially.

    • Take the smallest numbered leaf vv, remove it from the tree and append the unique neighbour that was adjacent to vv to the sequence.

    • Repeat the above step until the tree has only 22 vertices.

    1. Prove that there is a one to one correspondence between the sequence of length n2n-2 and the labelled tree.
    2. Find the total number of labelled trees of nn vertices using this reduction.
    3. Find the number of labelled trees with 1010 vertices whose degree of ithi^{th} vertex is a[i]a[i] where a[i]=[5,4,2,1,1,1,1,1,1,1]a[i] = [5,4,2,1,1,1,1,1,1,1].
  8. Let AA be an n×nn \times n diagonal matrix with characteristic polynomial (xc1)d1(xc2)d2...(xck)dk(x - c_1)^{d_1} (x - c_2)^{d_2} * ... * (x - c_k)^{d_k} where c1,c2,...,ckc_1, c_2, ..., c_k are distinct. Let VV be the vector space of all n×nn \times n matrices BB such that AB=BAAB = BA. Prove that the dimension of VV is d12+d22+...+dk2d_1^2 + d_2^2 + ... + d_k^2.

  9. There are nn participants in a game, where each of them plays a match against the other. The winner gets 11 point, while the loser gets 00. In case of a draw, both the players get 0.50.5. It is observed that for every player half of their points come from playing against the bottom 1010 ranked players, including these bottom 1010 players. Find the value of nn.

  10. There are 22 boxes. You can do nn operations on them. In each operation, you can either do a take move or a put move. In a put move, $1 is placed randomly into one of the two boxes with equal probability. In a take move, you gain all the money in one of the randomly chosen boxes. What is the maximum expected payout if you play optimally?

  11. There are 1010 males and 1010 females that you need to seat at a round dining table. In how many ways can you seat them so that every man is sitting beside at least 1 woman?

  12. Given S=(a,b,c,d)S = (a,b,c,d), T(S)=(ab,bc,cd,da)T(S) = (|a-b|, |b-c|, |c-d|, |d-a|), does the series S,T(S),T(T(S)),T(T(T(S)))....S, T(S), T(T(S)), T(T(T(S))).... converge?

  13. There is a sequence of 100100 coins, that have already been flipped. Alice starts checking each coin from the beginning to the end. Bob first checks the coins at even positions, and then the coins at the odd positions. The first one to find 26 heads wins. Who is more likely to win the game?

Samsung Research Institute Noida

Question

There are nn fishing spots on a lake, numbered from 11 to nn. There are mm fishermen waiting to get in. There are 33 gates, located at positions x[i]x[i] and having arr[i]arr[i] employees at gate ii. The distance between consecutive spots is 11, and the distance between the gate and the nearest spot is also 11. Only 11 gate can be opened at a time and all fishermen of that gate must occupy spots before next gate is open. Each fisherman will occupy the nearest spot to the gate greedily. It can be seen that all the employees at a gate will occupy a fixed position, except the last one who might have 22 spots to choose from. Write a program to return sum of minimum distance that the fishermen need to walk.

Constraints:


Codenation (Trilogy Innovations)

Other Campus Questions

  1. An array is considered valid if there is no subarray longer than BB where all elements are identical. Additionally, the array can only contain integers from the range [1,C][1, C]. Determine the number of valid arrays of length AA. Since the result can be very large, return it modulo 109+710^9+7.

    Problem Constraints:

    • 1A1091 \leq A \leq 10^9
    • 1Bmin(50,A)1 \leq B \leq min(50, A)
    • 1C1051 \leq C \leq 10^5
    Solution

    If the array length was upto 10510^5, then we could have used a simple DP solution where we can define dp[i]dp[i] as the number of valid suffixes starting from index ii. As a part of the transition at index ii, we can take the new element to occur xx times (between 11 and BB), and thus add the value for dp[i+x]dp[i + x]. Further, the number of possible values of this new element would be CC if the index is 00, and would be C1C - 1 otherwise (as it cannot be equal to the previous element). The overall complexity of this solution would be O(AB)O(A * B).

    But this solution is not feasible for A=109A = 10^9. We will make use of binary matrix exponentiation to solve this problem.

    Let us maintain a matrix MlM_l of size BB where M[j]M[j] at any point denotes how many valid arrays exist with the last element of the array occuring jj times for the current length ll. We can then define the transition to the next matrix Ml+1M_{l+1} representing the length l+1l + 1 as:

    • For j=1j = 1, we can a new element (with C1C - 1 possible values) to each of the jj elements in the previous array. Thus Ml+1[1]=(C1)(j=1BMl[j])M_{l+1}[1] = (C - 1) * (\sum_{j = 1}^{B} M_l[j]).
    • For j1j \neq 1, we can only transition using the same element as the previous one. Thus Ml+1[j]=Ml[j1]M_{l+1}[j] = M_l[j - 1].

    We can see that these transitions are independent of the vlaue of ll!

    Using these facts, we can define a transition matrix XX of size B×BB \times B to denote the number of ways to transition from current length ll to the next length l+1l + 1.

    Ml+1=Ml×[C1C1C1C1100001000010]\begin{array}{l} M_{l+1} = M_l \times \begin{bmatrix} C-1 & C-1 & C-1 & \cdots & C-1\\ 1 & 0 & 0 & \cdots & 0\\ 0 & 1 & 0 & \cdots & \vdots \\ \vdots & \ddots & \ddots & 0 & \vdots \\ 0 & \cdots & 0 & 1 & 0 \end{bmatrix} \\ \end{array}

    M1=[C1C1C1C1]\begin{array}{l} M_1 = \begin{bmatrix} C-1 & C-1 & C-1 & \cdots & C-1\\ \end{bmatrix} \\ \end{array}

    Then we can set the state for the initial matrix of length 11 as M1[1]=CM_1[1] = C and M1[j]=0M_1[j] = 0 for j1j \neq 1. We can then calculate the matrix MM for length AA as MA=MXA1M_A = M * X^{A - 1}.

    The overall complexity of this solution would be O(B3logA)O(B^3 \log A) where B3B^3 is the complexity of matrix multiplication and logA\log A is the complexity of matrix exponentiation.

    1
    long long MOD = 1e9 + 7;
    2
    3
    class Matrix
    4
    {
    5
    public:
    6
    vector<vector<long long>> arr;
    7
    8
    Matrix(vector<vector<long long>> arr) : arr(arr) {}
    9
    10
    Matrix multiply(Matrix &b)
    11
    {
    12
    int Y = arr.size(), X = b.arr[0].size();
    13
    vector<vector<long long>> res(Y, vector<long long>(X, 0));
    14
    15
    for (int y = 0; y < Y; y++)
    16
    for (int x = 0; x < X; x++)
    17
    for (int k = 0; k < arr[0].size(); k++)
    18
    {
    19
    res[y][x] += arr[y][k] * b.arr[k][x];
    20
    res[y][x] %= MOD;
    21
    }
    22
    23
    return Matrix(res);
    24
    }
    25
    26
    Matrix power(long long n)
    27
    {
    28
    int Y = arr.size();
    29
    30
    // Start with identity matrix
    31
    vector<vector<long long>> iden(Y, vector<long long>(Y));
    32
    for (int i = 0; i < Y; i++)
    33
    iden[i][i] = 1;
    34
    35
    Matrix a = Matrix(arr);
    36
    Matrix res = Matrix(iden);
    37
    38
    while (n)
    39
    {
    40
    if (n % 2 == 1)
    41
    res = res.multiply(a);
    42
    a = a.multiply(a);
    43
    n >>= 1;
    44
    }
    45
    46
    return res;
    47
    }
    48
    };
    49
    50
    int solve(int A, int B, int C)
    51
    {
    52
    vector<vector<long long>> l0(1, vector<long long>(B, 0));
    53
    l0[0][0] = C;
    54
    55
    vector<vector<long long>> tr(B, vector<long long>(B, 0));
    56
    for (int i = 0; i < B; i++)
    57
    {
    58
    tr[i][0] = C - 1;
    59
    if (i + 1 < B)
    60
    tr[i][i + 1] = 1;
    61
    }
    62
    63
    Matrix m = Matrix(l0), t = Matrix(tr);
    64
    t = t.power(A - 1);
    65
    Matrix res = m.multiply(t);
    66
    67
    long long ans = 0;
    68
    for (int i = 0; i < B; i++)
    69
    {
    70
    ans += res.arr[0][i];
    71
    ans %= MOD;
    72
    }
    73
    74
    return ans;
    75
    }
  2. Given is the pseudocode below to find a target number ii between ll and rr (both inclusive):

    while (l < r) {
    int mid = (l + r) / 2;
    if (i < mid) r = mid - 1;
    else if (i > mid) l = mid + 1;
    else {
    print("Found");
    break;
    }
    }

    You are required to answer qq queries, where in each query, you will be provided with values ll and rr. For each query, determine what is the probability that the above code will fail to print “Found” when any value ii (where lirl \leq i \leq r) is chosen?

    Express this probability as an integer where the fraction is PQ\frac{P}{Q} and gcd(P,Q)=1gcd(P, Q) = 1. You should compute PQ1P * Q^{-1} modulo 109+710^9+7, where Q1Q^{-1} is the modular inverse of QQ modulo 109+710^9+7.

    Problem Constraints:

    • 1A[i][0]A[i][1]1061 \leq A[i][0] \leq A[i][1] \leq 10^6
    Solution

    It can be observed that the output of the code only depends on the length of the array that we are searching in, and the actual values of ll and rr are irrelevant. Thus we can simplify the problem to finding the probability that the code will fail to print “Found” for an array of length nn.

    Let us calculate the value cnt[i]cnt[i] where cnt[i]cnt[i] denotes the number of values of ii such that the code will print Found for an array of length ii. It can be seen that in the base case cnt[0]=cnt[1]=0cnt[0] = cnt[1] = 0 (as the algorithm chooses the wrong endpoint in these cases).

    For i2i \geq 2, we can see that the code will always print Found for the middle element of the array. After that the problem would be reduced to counting the number of valid values in the left and right subarrays. Thus we can define the following recursive formula:

    • If ii is even, then cnt[i]=1+cnt[i/2]+cnt[ii/21]cnt[i] = 1 + cnt[i/2] + cnt[i - i/2 - 1] as ii/21i - i/2 - 1 is the number of elements in the left subarray, and i/2i/2 is the number of elements in the right subarray.
    • If ii is odd, then cnt[i]=1+2cnt[i/2]cnt[i] = 1 + 2*cnt[i/2] as both the left and right subarrays would have the same number of elements.

    Once we have these counts, finding the required probability is trivial.

    1
    long long MOD = 1e9 + 7;
    2
    3
    long long power(long long a, long long b)
    4
    {
    5
    long long res = 1;
    6
    7
    while (b)
    8
    {
    9
    if (b % 2 == 1)
    10
    {
    11
    res *= a;
    12
    res %= MOD;
    13
    }
    14
    a *= a;
    15
    a %= MOD;
    16
    b >>= 1;
    17
    }
    18
    19
    return res;
    20
    }
    21
    22
    vector<int> solve(vector<vector<int>> queries)
    23
    {
    24
    const int MAXN = 1e6;
    25
    vector<long long> cnt(MAXN + 1, 0);
    26
    27
    for (int i = 2; i <= MAXN; i++)
    28
    {
    29
    int k = i / 2;
    30
    if (i % 2 == 1)
    31
    cnt[i] = 1LL + 2LL * cnt[k];
    32
    else
    33
    cnt[i] = 1LL + cnt[k] + cnt[k - 1];
    34
    cnt[i] %= MOD;
    35
    }
    36
    37
    int n = queries.size();
    38
    vector<int> ans;
    39
    40
    for (auto q : queries)
    41
    {
    42
    int l = q[1] - q[0] + 1;
    43
    long long pr = (l - cnt[l]) * power(l, MOD - 2);
    44
    pr %= MOD;
    45
    ans.push_back(pr);
    46
    }
    47
    48
    return ans;
    49
    }
  3. You are given an array arrarr consisting of NN integers. You are also given qq queries. Each query consists of three integers XX, YY, and ZZ. For each query find the largest contiguous subarray BB starting from index XX, whose YYth bit is set, and then update each of its elements BjB_j with BjZB_j \oplus Z where \oplus denotes the bitwise XOR operator.

    Your task is to print the total number of updates performed after qq queries. Given a 2D2D array matmat that represents the queries:

    • mat[i][0]=Xmat[i][0] = X
    • mat[i][1]=Ymat[i][1] = Y
    • mat[i][2]=Zmat[i][2] = Z

    Problem Constraints:

    • 1N1051 \leq N \leq 10^5
    • 0arr[i]1090 \leq arr[i] \leq 10^9
    • 1q1051 \leq q \leq 10^5
    • 1XN1 \leq X \leq N
    • 0Y300 \leq Y \leq 30
    • 0Z1090 \leq Z \leq 10^9
    Solution

    This question is quite an exercise on segment trees with lazy proportion & binary search. Let us create 3030 segment trees, on for each bit in the number of the arrays. This segment tree needs to support the following operations:

    • Getting the sum of the elements in a range. This can be done using the standard segment tree.
    • Flipping all the values in a range. This can be done using the lazy propagation technique and setting the value of a tree node to lnodeValuel - nodeValue where ll is the length of the range and nodeValuenodeValue is the current value of the node (this shows that all the 11s in the range are flipped to 00 and vice versa).

    Now, wherenever we get a query, we can do the following:

    • Perform a binary search to find the rightmost index where the YYth bit is set. When checking for an index rr starting from idxidx, we need to check that sum(idx,r)=ridx+1sum(idx, r) = r - idx + 1 where sumsum is the sum returned by the segment tree of bit YY.
    • Then for all the bits ii set in ZZ, we can flip the values in the range [idx,r][idx, r] for the segment tree of bit ii.

    The overall complexity of the solution would be O(30Q(Nlog2N+NlogN))O(30 * Q * (N \log^2 N + N \log N)), which requires careful implementation to pass the time limits.

    1
    int MAX_BITS = 30;
    2
    3
    class SegTree
    4
    {
    5
    public:
    6
    int n, bit;
    7
    vector<int> tree, lazy;
    8
    9
    SegTree(int bit, vector<int> &arr)
    10
    {
    11
    this->bit = bit;
    12
    n = arr.size();
    13
    14
    tree.resize(4 * n);
    15
    build(1, 0, n - 1, arr);
    16
    lazy.assign(4 * n, 0);
    17
    }
    18
    19
    void build(int v, int l, int r, vector<int> &arr)
    20
    {
    21
    if (l == r)
    22
    tree[v] = (arr[l] >> bit) & 1;
    23
    else
    24
    {
    25
    int m = (l + r) / 2;
    26
    build(2 * v, l, m, arr);
    27
    build(2 * v + 1, m + 1, r, arr);
    28
    tree[v] = tree[2 * v] + tree[2 * v + 1];
    29
    }
    30
    }
    31
    32
    void push(int v, int l, int m, int r)
    33
    {
    34
    if (!lazy[v])
    35
    return;
    36
    37
    tree[2 * v] = (m - l + 1) - tree[2 * v];
    38
    lazy[2 * v] ^= 1;
    39
    40
    tree[2 * v + 1] = (r - (m + 1) + 1) - tree[2 * v + 1];
    41
    lazy[2 * v + 1] ^= 1;
    42
    43
    lazy[v] = 0;
    44
    }
    45
    46
    void update(int v, int l, int r, int ql, int qr)
    47
    {
    48
    if (ql > qr)
    49
    return;
    50
    51
    if (l == ql && r == qr)
    52
    {
    53
    // Convert the cnt of 1 to cnt of 0's
    54
    tree[v] = (r - l + 1) - tree[v];
    55
    lazy[v] ^= 1;
    56
    return;
    57
    }
    58
    59
    int m = (l + r) / 2;
    60
    push(v, l, m, r);
    61
    62
    update(2 * v, l, m, ql, min(qr, m));
    63
    update(2 * v + 1, m + 1, r, max(m + 1, ql), qr);
    64
    tree[v] = tree[2 * v + 1] + tree[2 * v];
    65
    }
    66
    67
    int query(int v, int l, int r, int ql, int qr)
    68
    {
    69
    if (ql > qr)
    70
    return 0;
    71
    if (ql == l && qr == r)
    72
    return tree[v];
    73
    74
    int m = (l + r) / 2;
    75
    push(v, l, m, r);
    76
    77
    int q1 = query(2 * v, l, m, ql, min(qr, m));
    78
    int q2 = query(2 * v + 1, m + 1, r, max(m + 1, ql), qr);
    79
    return q1 + q2;
    80
    }
    81
    82
    void update(int l, int r)
    83
    {
    84
    update(1, 0, n - 1, l, r);
    85
    }
    86
    87
    int query(int l, int r)
    88
    {
    89
    return query(1, 0, n - 1, l, r);
    90
    }
    91
    };
    92
    93
    int solve(vector<int> arr, vector<vector<int>> que)
    94
    {
    95
    int totOps = 0;
    96
    int n = arr.size();
    97
    98
    vector<SegTree> tr;
    99
    for (int bit = 0; bit < MAX_BITS; bit++)
    100
    tr.push_back(SegTree(bit, arr));
    101
    102
    for (auto q : que)
    103
    {
    104
    int idx = q[0] - 1, bit = q[1] - 1, z = q[2];
    105
    106
    int l = idx, r = n - 1;
    107
    int ans = -1;
    108
    while (l <= r)
    109
    {
    110
    int m = (l + r) / 2;
    111
    if (tr[bit].query(idx, m) == m - idx + 1)
    112
    {
    113
    ans = m;
    114
    l = m + 1;
    115
    }
    116
    else
    117
    r = m - 1;
    118
    }
    119
    120
    if (ans != -1)
    121
    {
    122
    totOps += ans - idx + 1;
    123
    for (int i = 0; i < MAX_BITS; i++)
    124
    if ((z >> i) & 1)
    125
    tr[i].update(idx, ans);
    126
    }
    127
    }
    128
    129
    return totOps;
    130
    }
  4. You are a book collector aiming to sell your collection of AA books. The books are arranged in a line with the ithi^{th} book to the left of the (i+1)(i + 1)th book. The thickness of each book is represented by an array BB (where B[i]B[i] is the thickness of the ithi^{th} book) and each book has a unique thickness.

    To enhance the appeal of your books, you can apply a special protective covering to some of them. However, this cover is expensive and thus you want tp minimize its use while ensuring the following conditions are met:

    • You should apply the cover to at least one book.
    • If you apply the cover to the ithi^{th} book, you must also apply the cover all books that are thicker than the ithi^{th} book.
    • There must exist at least one subarray (contiguous segment) of books of size at least CC such that the number of books with the protective cover is greater than the number of books without the cover.

    Your task is to determine the smallest number of books on which you should apply the protective cover to satify the above conditions.

    Problem Constraints:

    • 1A1051 \leq A \leq 10^5
    • 1B[i]A(1i<jn,B[i]B[j])1 \leq B[i] \leq A (1 \leq i < j \leq n, B[i] \neq B[j])
    • 1CA1 \leq C \leq A
    Solution

    Let us fix the minimum thickness of the book that we must cover as tt. It can easilu be argued that if there exists a subarray satisfying the third condition for tt, then the same subarray would also be valid for all t<tt' < t. This gives us the idea that we can binary search on the minimum thickess tt hoping to maximize the same.

    To check if there is a subarray that satifies condition 3 for a particular tt, we can make the following construction: Create a new array bb where b[i]=1b[i] = 1 if arr[i]tarr[i] \geq t else it is 1-1. Now the third question reduces to finding if there is a subarray of atleast size CC in bb such that the sum of the elements in the subarray is greater than 00.

    This is a pretty standard problem which can be solved with the concepts of prefix sums and minimums (Reading about 2 Sum problem on Leetcode and all it’s possible extensions) in O(N)O(N) time. Thus the overall complexity of the solution would be O(NlogA)O(N \log A) where AA is the maximum thickness of the book.

    1
    bool checkValid(int mi, int n, vector<int> &base, int k)
    2
    {
    3
    vector<int> arr(n), pre(n + 1), preMin(n + 1);
    4
    5
    for (int i = 0; i < n; i++)
    6
    arr[i] = base[i] >= mi ? 1 : -1;
    7
    8
    for (int i = 1; i <= n; i++)
    9
    {
    10
    pre[i] = arr[i - 1] + pre[i - 1];
    11
    preMin[i] = min(pre[i], preMin[i - 1]);
    12
    }
    13
    14
    for (int i = k; i <= n; i++)
    15
    if (pre[i] - preMin[i - k] > 0)
    16
    return true;
    17
    18
    return false;
    19
    }
    20
    21
    int solve(int n, vector<int> arr, int k)
    22
    {
    23
    int l = 0, r = *max_element(arr.begin(), arr.end());
    24
    int ans = -1;
    25
    26
    while (l <= r)
    27
    {
    28
    int m = l + (r - l) / 2;
    29
    if (checkValid(m, n, arr, k))
    30
    {
    31
    // Update the answer count
    32
    ans = 0;
    33
    for (int i : arr)
    34
    if (i >= m)
    35
    ans++;
    36
    37
    // Update the bounds
    38
    l = m + 1;
    39
    }
    40
    else
    41
    r = m - 1;
    42
    }
    43
    44
    return ans;
    45
    }
  5. The teacher in Bitland writes the numbers from 11 to AA (inclusive) on Blackboard. Now, he gives the following task:

    • Choose some numbers (possibly all or none) from the blackboard.
    • The bitwise XOR of the chosen numbers should be equal to 00 (If you pick no elements, bitwise XOR is considered to be 00).
    • The count of chosen numbers should be maximum.
    • If there are multiple possible options which yield maximum count, then choose the one with minimum sum.
    • If there are still multiple possible options, choose the one which is lexicographically smallest.

    Problem Constraints:

    • 1A1051 \leq A \leq 10^5
  6. You are a librarian, and after a long day, you decide to collect all the books kept on tables. In front of you, there are several stacks of books. A[i]A[i] denotes the size of the ithi^{th} stack of books. In one move you can pick an existing stack and merge it with another stack of books. The efforts required for this task is the size of stack being added. You have also decided that for any stack you will not add books to it for more than BB times added to any other stack. What is the minimum effort required to collect all the books in one stack?

    Problem Constraints:

    • 1A1051 \leq |A| \leq 10^5
    • 1A[i]<=1091 \leq A[i] <= 10^9
    • 1B1051 \leq B \leq 10^5

Questions

  1. A cryptarithm is a mathematical puzzle where the goal is to find the correspondence between letters and digits such that the given arithmetic equation consisting of letters holds true. Given a cryptarithm as an array of strings cryptcrypt, count the number of its valid solutions.

    The solution is valid if each letter represents a different digit, and the leading digit of a multi-digit number is not zero. The cryptarithm contains only capital letters and does not contain any leading zeros. cryptcrypt has the following structure: [wordl,word2,word3][wordl, word2, word3], which stands for the word1+word2=word3word1 + word2 = word3 cryptarithm. Is is guranteed that the length of the cryptarithm is 33.

    Constraints:

    • 1crypt[i].length351 \leq crypt[i].length \leq 35
    • Acrypt[i][j]ZA \leq crypt[i][j] \leq Z
  2. You are given a string of the form a/b+c/d where a,b,c,da, b, c, d are integers upto 20002000. You need to calculate the value ab+cd\frac{a}{b} + \frac{c}{d} in the simplest form as pq\frac{p}{q} where pp and qq are coprime integers. Return a string of the form p/q.

  3. You are given an array called balancebalance where balance[i]balance[i] denotes the balance of the ithi^{th} account. You are also given an array requestsrequests where requests[i]requests[i] denotes the ithi^{th} transaction request. Each transaction request is a string of the form timestamp [withdraw|deposit] amount accountIdx. You need to process these requests subject to the following conditions:

    • The timestamps are processed in increasing order & in seconds.
    • A transaction may be invalid if the account balance is less than the amount to be withdrawn or the accountIdx is invalid.
    • As soon as you encouter an invalid transaction, you need to stop processing the requests. If the 11 based index of the first invalid transaction is ii, you need to return a vector with a single element equal to i-i.
    • If all the transactions are valid, you need to return the final balance of all the accounts.
    • The bank has an additional offer. Whenever amount xx is withdrawn from an account, the bank automatically credits a cashbacks c=2x100c = \lfloor \frac{2x}{100} \rfloor to the account after 2424 hours of the withdrawn.
    • Return the balances just after processing the last transaction, and do not wait for the pending cashbacks (if any) to complete.
  4. You are given two ListNode heads aa and bb. Each list represents a huge number, and each list node represents exactly 44 digits of the number. You need to return the sum of the two numbers as a linked list. The numbers may have leading zeros. (For example, if a=[1,20,333,4124]a = [1, 20, 333, 4124] then it actually represents the number 10002000333041241000200033304124)

    class ListNode {
    public:
    int val;
    ListNode *next;
    ListNode(int val) : val(val), next(nullptr) {}
    };

Deustche Bank

Other Campus Questions

A lot of these questions have been mixed with questions that were asked in the internship season of 2024 for Deustche Bank!

  1. You are given a binary string ss of length nn. What is the largest prime number whose binary representation can be formed by deleting some digits from the string ss? The length of the string ss is at most 2020.

    Solution

    Since the length of the string is at most 2020, we can generate all the prime numbers up to 22012^{20} - 1 and store their binary representations in a trie. Then, we can perform a DFS on the trie to find the largest prime number that can be formed as a subsequence of the given string, by greeding selecting the next bit from the string.

    Time Complexity: O(2n+2n)O(2^n + 2n)

    1
    class Node
    2
    {
    3
    public:
    4
    Node *ch[2];
    5
    int val;
    6
    7
    Node()
    8
    {
    9
    ch[0] = ch[1] = NULL;
    10
    val = -1;
    11
    }
    12
    };
    13
    14
    class Trie
    15
    {
    16
    public:
    17
    Node *root;
    18
    19
    Trie()
    20
    {
    21
    root = new Node();
    22
    }
    23
    24
    void insert(int x)
    25
    {
    26
    int org = x;
    27
    28
    string bits = "";
    29
    while (x)
    30
    {
    31
    bits += (x & 1) + '0';
    32
    x >>= 1;
    33
    }
    34
    reverse(bits.begin(), bits.end());
    35
    36
    Node *cur = root;
    37
    for (char bit : bits)
    38
    {
    39
    if (cur->ch[bit - '0'] == NULL)
    40
    cur->ch[bit - '0'] = new Node();
    41
    cur = cur->ch[bit - '0'];
    42
    }
    43
    cur->val = org;
    44
    }
    45
    };
    46
    47
    void dfs(Node *cur, int idx, string &s, int &ans)
    48
    {
    49
    if (cur->val != -1)
    50
    ans = max(ans, cur->val);
    51
    52
    int nextZeroIdx = -1, nextOneIdx = -1;
    53
    while (idx < s.size() && (nextZeroIdx == -1 || nextOneIdx == -1))
    54
    {
    55
    if (s[idx] == '0' && nextZeroIdx == -1)
    56
    nextZeroIdx = idx;
    57
    else if (s[idx] == '1' && nextOneIdx == -1)
    58
    nextOneIdx = idx;
    59
    idx++;
    60
    }
    61
    62
    if (nextZeroIdx != -1 && cur->ch[0] != NULL)
    63
    dfs(cur->ch[0], nextZeroIdx + 1, s, ans);
    64
    65
    if (nextOneIdx != -1 && cur->ch[1] != NULL)
    66
    dfs(cur->ch[1], nextOneIdx + 1, s, ans);
    67
    }
    68
    69
    int solve(string s)
    70
    {
    71
    int MAXN = 0;
    72
    73
    int n = s.size();
    74
    for (int i = 0; i < n; i++)
    75
    if (s[i] == '1')
    76
    MAXN |= (1 << (n - 1 - i));
    77
    78
    vector<int> isPrime(MAXN + 1, 1);
    79
    isPrime[0] = isPrime[1] = 0;
    80
    for (int i = 2; i * i <= MAXN; i++)
    81
    if (isPrime[i])
    82
    for (int j = i * i; j <= MAXN; j += i)
    83
    isPrime[j] = 0;
    84
    85
    Trie trie;
    86
    for (int i = 1; i <= MAXN; i++)
    87
    if (isPrime[i])
    88
    trie.insert(i);
    89
    90
    int ans = -1;
    91
    dfs(trie.root, 0, s, ans);
    92
    93
    return ans;
    94
    }

    On second thought, we have a simpler implementation available since nn is small. We can directly use bitmasks to generate all the subsequences of the provided string and check if the number formed by the same is prime or not. The complexity of this solution would be O(2nn+AloglogA)O(2^n \cdot n + A \log \log A) where A=2nA = 2^n.

  2. You are given a string ss of length nn containing only the characters aa and bb. Find the lexographically smallest subsequence of ss of length kk with atleast xx bb‘s. Return an empty string if no such subsequence exits.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1kn1 \leq k \leq n
    • 0xn0 \leq x \leq n
    Solution

    Take the bb characters from the end of the string as much as possible, and then take the aa characters from the beginning of the string as much as possible. There is some edge case handling required related to the count of the characters. The time complexity of the solution is O(n)O(n).

    1
    string solve(int s, int k, int x) {
    2
    int n = s.size();
    3
    if (k > n) return "";
    4
    5
    int cntA = 0, cntB = 0;
    6
    for (int i = 0; i < n; i++) {
    7
    if (s[i] == 'a') cntA++;
    8
    else cntB++;
    9
    }
    10
    11
    if (cntB < x) return "";
    12
    13
    int useA = min(cntA, k - x);
    14
    int useB = k - useA;
    15
    16
    vector<int> idx, AIdx, BIdx;
    17
    for (int i = 0; i < n; i++) {
    18
    if (s[i] == 'a') AIdx.push_back(i);
    19
    else BIdx.push_back(i);
    20
    }
    21
    22
    for (int i = 0; i < useA; i++) idx.push_back(AIdx[i]);
    23
    reverse(BIdx.begin(), BIdx.end());
    24
    for (int i = 0; i < useB; i++) idx.push_back(BIdx[i]);
    25
    26
    sort(idx.begin(), idx.end());
    27
    string ans = "";
    28
    for (int i : idx) ans += s[i];
    29
    30
    return ans;
    31
    }
  3. You are given a grid of size n×mn \times m containg some free cells (marked as .) and some blocked cells (marked as #). You take 11 minute to travel from one cell to the other. You can only move horizontally or vertically. You are given the coordinates of the starting cell and the ending cell. Find the minimum time required to reach the ending cell from the starting cell.

    Constraints:

    • 1n,m1031 \leq n, m \leq 10^3
    • 1x1,y1,x2,y2n1 \leq x_1, y_1, x_2, y_2 \leq n
  4. A number is called beautiful if it atleast contains one bit as 00, and atmost 33 bits as 00 in it’s binary representation. Given multiple queries of the form [l,r][l, r], find the sum of the cubes of all the beautiful numbers in the range [l,r][l, r]. Print the sum modulo 998244353998244353.

    Constraints:

    • 1lr10181 \leq l \leq r \leq 10^{18}
    • 1q21051 \leq q \leq 2 \cdot 10^5
    Solution

    We can use a simple brute force to generate all the possible beautiful numbers, and then use prefix sums and binary search to calculate the sum of the cubes of these numbers in any range. The time complexity of the solution is O(604+qlogN)O(60^4 + q \log N) where NN is the total number of beautiful numbers (N105N \leq 10^5).

    1
    int main()
    2
    {
    3
    int MAX_BITS = 60;
    4
    5
    set<long long> validNumbers;
    6
    7
    for (int len = 1; len <= MAX_BITS; len++)
    8
    {
    9
    long long allSet = (1LL << len) - 1;
    10
    11
    // The last bit is always set, thus the last variable is only upto len - 1
    12
    // 1 unset
    13
    for (int i = 0; i < len - 1; i++)
    14
    validNumbers.insert(allSet ^ (1LL << i));
    15
    16
    // 2 unset
    17
    for (int i = 0; i < len; i++)
    18
    for (int j = i + 1; j < len - 1; j++)
    19
    validNumbers.insert(allSet ^ (1LL << i) ^ (1LL << j));
    20
    21
    // 3 unset
    22
    for (int i = 0; i < len; i++)
    23
    for (int j = i + 1; j < len; j++)
    24
    for (int k = j + 1; k < len - 1; k++)
    25
    validNumbers.insert(allSet ^ (1LL << i) ^ (1LL << j) ^ (1LL << k));
    26
    }
    27
    28
    long long MOD = 998244353;
    29
    30
    vector<long long> preSum, arr;
    31
    for (long long x : validNumbers)
    32
    {
    33
    arr.push_back(x);
    34
    x %= MOD;
    35
    x = (((x * x) % MOD) * x) % MOD;
    36
    long long last = preSum.empty() ? 0 : preSum.back();
    37
    preSum.push_back((last + x) % MOD);
    38
    }
    39
    40
    int q;
    41
    cin >> q;
    42
    43
    while (q--)
    44
    {
    45
    long long l, r;
    46
    cin >> l >> r;
    47
    48
    int idxLow = lower_bound(arr.begin(), arr.end(), l) - arr.begin();
    49
    int idxUp = upper_bound(arr.begin(), arr.end(), r) - arr.begin() - 1;
    50
    long long ans = 0;
    51
    if (idxUp >= idxLow)
    52
    {
    53
    ans = preSum[idxUp];
    54
    if (idxLow > 0)
    55
    ans = (ans - preSum[idxLow - 1] + MOD) % MOD;
    56
    }
    57
    58
    cout << ans << endl;
    59
    }
    60
    }
    Extension

    If the question revolved around finding the number of beautiful numbers in the range [l,r][l, r], or just the sum of all the beautiful numbers in the range [l,r][l, r], then we could have used a simple digit DP based approach to solve the problem (as addition is distributive over modulo operation). The time complexity of the solution would have been O(Q(644222)2)O(Q \cdot (64 \cdot 4 \cdot 2 \cdot 2 \cdot 2)\cdot 2).

    1
    long long MOD = 998244353;
    2
    using pll = pair<long long, long long>;
    3
    4
    // idx: Current index
    5
    // cnt0: Number of 0's in the number
    6
    // eq: Whether the number is equal to the given number
    7
    // started: Whether the number has started (to avoid leading zeros)
    8
    pll countWithSum(int idx, int cnt0, bool eq, bool started, string &s, pll dp[][4][2][2])
    9
    {
    10
    if (idx == s.size())
    11
    return {cnt0 > 0, 0};
    12
    13
    if (dp[idx][cnt0][eq][started].first != -1)
    14
    return dp[idx][cnt0][eq][started];
    15
    16
    long long ways = 0, sum = 0;
    17
    int maxDigit = eq ? (s[idx] - '0') : 1;
    18
    19
    for (int bit = 0; bit <= maxDigit; bit++)
    20
    {
    21
    bool newStarted = started || (bit == 1);
    22
    int newCnt0 = cnt0 + (newStarted && (bit == 0));
    23
    bool newEq = eq && (bit == maxDigit);
    24
    25
    if (newCnt0 > 3)
    26
    continue;
    27
    28
    auto [waysToAdd, sumToAdd] = countWithSum(idx + 1, newCnt0, newEq, newStarted, s, dp);
    29
    ways += waysToAdd;
    30
    ways %= MOD;
    31
    32
    sum += sumToAdd;
    33
    if (bit == 1)
    34
    sum += waysToAdd * ((1LL << (s.size() - 1 - idx)) % MOD);
    35
    sum %= MOD;
    36
    }
    37
    38
    return dp[idx][cnt0][eq][started] = {ways, sum};
    39
    }
    40
    41
    string getBinary(long long x)
    42
    {
    43
    string ans = "";
    44
    while (x)
    45
    {
    46
    ans += (x & 1) + '0';
    47
    x >>= 1;
    48
    }
    49
    reverse(ans.begin(), ans.end());
    50
    return ans;
    51
    }
    52
    53
    long long getSum(string s)
    54
    {
    55
    int n = s.size();
    56
    pll dp[n][4][2][2];
    57
    memset(dp, -1, sizeof(dp));
    58
    59
    auto [ways, sum] = countWithSum(0, 0, 1, 0, s, dp);
    60
    return sum;
    61
    }
    62
    63
    vector<int> countBeautifulNumbers(vector<pll> queries)
    64
    {
    65
    vector<int> ans;
    66
    67
    for (auto [l, r] : queries)
    68
    {
    69
    string L = getBinary(l - 1);
    70
    string R = getBinary(r);
    71
    72
    long long cntL = getSum(L);
    73
    long long cntR = getSum(R);
    74
    75
    ans.push_back((cntR - cntL + MOD) % MOD);
    76
    }
    77
    78
    return ans;
    79
    }
  5. You are given an array aa and who empty arrays ss and tt. The array aa is a permutation of length nn. In one operation, you can do one of the following:

    • Remove the element from the starting of aa and add it to the end of tt.
    • Remove the element from the starting of aa and add it to the end of ss.
    • Remove the element from the starting of ss and add it to the end of tt

    Determine if it is possible to obtain the sorted permutation in the array tt.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    Solution

    We will use a greedy approach, where we will try to find the currently needed element from both ss and aa, and if not found, we would move the elements from aa to ss in hopes of finding the currently required element. The time complexity is O(n)O(n).

    int main()
    {
    int n;
    cin >> n;
    queue<int> a, b;
    for (int i = 0; i < n; i++)
    {
    int x;
    cin >> x;
    a.push(x);
    }
    int need = 1;
    while (need != n + 1)
    {
    if (!a.empty() && a.front() == need)
    {
    a.pop();
    need++;
    }
    else if (!b.empty() && b.front() == need)
    {
    b.pop();
    need++;
    }
    else
    {
    while (!a.empty() && a.front() != need)
    {
    b.push(a.front());
    a.pop();
    }
    if (a.empty())
    {
    cout << "NO\n";
    return 0;
    }
    }
    }
    cout << "YES\n";
    }
  6. You are given a tree with nn nodes rooted at 11. In one operation, you can break any edge of the tree. Even after breaking the edge, the original parent-child relation between the nodes will hold. Minimize the number of operations needed to be performed so as convert the tree into a valid kk -nary tree. After minimising the operations, also return the maximum size of the tree possible.

    Solution
    1
    void dfs(int u, vector<vector<int>> &g, vector<int> &subtree, int k, int &ops, int &maxSize)
    2
    {
    3
    subtree[u] = 1;
    4
    int childCnt = 0;
    5
    vector<int> sz;
    6
    7
    for (int v : g[u])
    8
    {
    9
    dfs(v, g, subtree, k, ops, maxSize);
    10
    childCnt++;
    11
    subtree[u] += subtree[v];
    12
    sz.push_back(subtree[v]);
    13
    }
    14
    15
    int toRem = childCnt % k;
    16
    sort(sz.begin(), sz.end());
    17
    for (int i = 0; i < toRem; i++)
    18
    {
    19
    subtree[u] -= sz[i];
    20
    ops++;
    21
    }
    22
    23
    maxSize = max(maxSize, subtree[u]);
    24
    }
    25
    26
    int main()
    27
    {
    28
    int t;
    29
    cin >> t;
    30
    while (t--)
    31
    {
    32
    int n, k;
    33
    cin >> n >> k;
    34
    35
    vector<vector<int>> g(n);
    36
    for (int i = 1; i < n; i++)
    37
    {
    38
    int x;
    39
    cin >> x;
    40
    g[x - 1].push_back(i);
    41
    }
    42
    43
    int maxSize = 0, ops = 0;
    44
    vector<int> sub(n);
    45
    dfs(0, g, sub, k, ops, maxSize);
    46
    cout << ops << " " << maxSize << "\n";
    47
    }
    48
    }
  7. You are given a tree with nn vertices, and each vertice has a colour as 00 or 11. For a node, we define the beauty of the vertex as the number of paths in the subtree of the node that have different colours of the ending points. Find the beauty of each node in the tree when the tree is rooted at vertex 11.

    Solution

    We can perform a simple DFS to calculate the number of nodes with colour 00 and colour 11 in the subtree of each node. The beauty of a node is then the product of the number of nodes with colour 00 and colour 11 in the subtree of the node. The time complexity of the solution is O(n)O(n).

    1
    vector<int> getBeauty(int n, string col, vector<vector<int>> &edges)
    2
    {
    3
    vector<vector<int>> g(n);
    4
    for (auto &e : edges)
    5
    {
    6
    e[0]--, e[1]--;
    7
    g[e[0]].push_back(e[1]);
    8
    g[e[1]].push_back(e[0]);
    9
    }
    10
    11
    vector<vector<int>> subCnt(n, vector<int>(2));
    12
    13
    function<void(int, int)> dfs = [&](int u, int p) -> void
    14
    {
    15
    subCnt[u][col[u] - '0'] = 1;
    16
    17
    for (int v : g[u])
    18
    {
    19
    if (v == p)
    20
    continue;
    21
    dfs(v, u);
    22
    subCnt[u][0] += subCnt[v][0];
    23
    subCnt[u][1] += subCnt[v][1];
    24
    }
    25
    };
    26
    27
    dfs(0, -1);
    28
    29
    vector<int> ans(n);
    30
    for (int i = 0; i < n; i++)
    31
    ans[i] = subCnt[i][0] * subCnt[i][1];
    32
    return ans;
    33
    }
  8. Given a sequence of nn integers (a1,a2,,an)(a_1, a_2, \ldots, a_n), you need to perform the following operation and return the obtained result.

    • For a given integer xx, calculate the value of the expression mini=1j=nx+1(fun(ai,ai+1,,ai+x1))min_{i = 1}^{j = n - x + 1} (fun(a_i, a_{i + 1}, \ldots, a_{i + x -1})), where fun(ai,ai+1,,ai+x1)fun(a_i, a_{i + 1}, \ldots, a_{i + x -1}) is the rightmost number with the highest number of distinct prime factors in the sequence (ai,ai+1,,ai+x1)(a_i, a_{i + 1}, \ldots, a_{i + x -1}).

    Constraints:

    • 1n1061 \leq n \leq 10^6
    • 1xn1 \leq x \leq n
    • 0ai1060 \leq a_i \leq 10^6
    Solution

    We can use the Sieve of Eratosthenes to compute the number of distinct prime factors of each number in the sequence. Then, we can use a sliding window of size xx and a priority queue to find the rightmost number with the highest number of distinct prime factors in the window. The priority queue would store the number of divisors of the element as well as it’s index. The time complexity of the solution is O(AlogA+nlogx)O(A \log A + n \log x) where AA is the maximum value of aia_i.

    1
    int getCntPrime(int n, vector<int> &spf)
    2
    {
    3
    int cnt = 0;
    4
    while (n > 1)
    5
    {
    6
    int p = spf[n];
    7
    cnt++;
    8
    while (n % p == 0)
    9
    n /= p;
    10
    }
    11
    12
    return cnt;
    13
    }
    14
    15
    int getValue(vector<int> &arr, int x)
    16
    {
    17
    int mx = 0, n = arr.size();
    18
    for (int i = 0; i < n; i++)
    19
    mx = max(mx, arr[i]);
    20
    21
    vector<int> spf(mx + 1);
    22
    for (int i = 0; i <= mx; i++)
    23
    spf[i] = i;
    24
    25
    for (int i = 2; i <= mx; i++)
    26
    if (spf[i] == i)
    27
    for (int j = i * i; j <= mx; j += i)
    28
    if (spf[j] == j)
    29
    spf[j] = i;
    30
    31
    int ans = 1e9;
    32
    priority_queue<pair<int, int>> pq;
    33
    34
    for (int i = 0; i < x - 1; i++)
    35
    pq.push({getCntPrime(arr[i], spf), i});
    36
    37
    for (int i = x - 1; i < n; i++)
    38
    {
    39
    pq.push({getCntPrime(arr[i], spf), i});
    40
    41
    while (pq.top().second <= i - x)
    42
    pq.pop();
    43
    ans = min(ans, arr[pq.top().second]);
    44
    }
    45
    46
    return ans;
    47
    }
  9. A function S(x)S(x) is defined as the sum of all the divisors for the number xx. The function F(x)F(x) is defined as the sum of S(y)S(y) for all the divisors yy of xx. Given two numbers ll and rr, find the sum of F(x)F(x) for all the numbers in the range [l,r][l, r] modulo 998244353998244353.

    Constraints:

    • 1lr1061 \leq l \leq r \leq 10^6
    Solution

    We can use a simple sieve like approach to calculate the sum of divisors of all the numbers in the range [1,r][1, r]. Then, we can again apply this sieve like approach to the sum of divisors to calculate the sum of F(x)F(x) for all the numbers in the range [1,r][1, r]. The time complexity of the solution is O(rlogr)O(r \log r).

    1
    long long MOD = 998244353;
    2
    3
    long long getSum(int l, int r)
    4
    {
    5
    vector<long long> sumDiv(r + 1, 0);
    6
    for (int i = 1; i <= r; i++) {
    7
    for (int j = i; j <= r; j += i) {
    8
    sumDiv[j] += i;
    9
    }
    10
    }
    11
    12
    vector<long long> sumF(r + 1, 0);
    13
    for (int i = 1; i <= r; i++) {
    14
    for (int j = i; j <= r; j += i) {
    15
    sumF[j] += sumDiv[i];
    16
    }
    17
    }
    18
    19
    long long ans = 0;
    20
    for (int i = l; i <= r; i++) {
    21
    ans += sumF[i];
    22
    ans %= MOD;
    23
    }
    24
    25
    return ans;
    26
    }

    This approach can easily be extended with precomputation to calculate the sum of F(x)F(x) for all the numbers in the range [l,r][l, r] in O(1)O(1) time for multiple queries.

  10. Given an array of size NN containing integers, find the minimum possible sum of that can be formed be adding the elements in the array. You can perform the following operation at most once:

    • Select an index. If the sum of all the elements in the array up to the selected index is a multiple of the element present at the index. divide the sum up to the selected index by the element present at the index.
    • After dividing, you do not have to add this element to the resultant sum.
    • After this operation is performed, you will have to add the remaining elements to the resultant sum.
    • Note that the chosen index is excluded from the prefix sum and the suffix sum. If the chosen index is 00, then it should be included in the prefix sum.

    Constraints:

    • 1N1061 \leq N \leq 10^6
    • 1Ai1061 \leq A_i \leq 10^6
    Solution

    We can use a prefix sum and a suffix sum to calculate the sum of all the elements in the array. Then, we can iterate over all the elements in the array and calculate the sum of all the elements in the array excluding the current element. The time complexity of the solution is O(N)O(N).

    1
    long long solve(vector<int> &arr) {
    2
    int n = arr.size();
    3
    4
    vector<long long> prefix(n), suffix(n);
    5
    prefix[0] = arr[0];
    6
    for (int i = 1; i < n; i++) {
    7
    prefix[i] = prefix[i - 1] + arr[i];
    8
    }
    9
    suffix[n - 1] = arr[n - 1];
    10
    for (int i = n - 2; i >= 0; i--) {
    11
    suffix[i] = suffix[i + 1] + arr[i];
    12
    }
    13
    14
    long long ans = prefix[n - 1];
    15
    16
    for (int i = 0; i < n; i++) {
    17
    long long pre = i == 0 ? 0 : prefix[i - 1];
    18
    long long suf = i == n - 1 ? 0 : suffix[i + 1];
    19
    20
    if (pre % arr[i] == 0) {
    21
    ans = min(ans, pre / arr[i] + suf);
    22
    }
    23
    }
    24
    25
    return ans;
    26
    }
  11. Given an integer array arrarr of integers of length nn, find the largest possible value xx such that atleast kk elements of the array are divisible by the same.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1kn1 \leq k \leq n
    • 1arr[i]1061 \leq arr[i] \leq 10^6
    Solution

    We can precompute all the divisors of all the numbers upto 10610^6 using the Sieve of Eratosthenes. Then, we can iterate over all the divisors of any number in the array, and check if it a valid divisor satifying the condition. Since a number till 10610^6 can have atmost 128128 divisors, this solution would work in O(n128+AlogA)O(n \cdot 128 + A \log A) time where AA is 10610^6 for precomputation. We would need careful handling of the case when the numbers are 00, and a streamlined implementation to avoid TLE in a 11 second time limit.

    1
    void precomputeDivisors(int n, vector<vector<int>> &divisors)
    2
    {
    3
    divisors.resize(n + 1);
    4
    for (int i = 1; i <= n; i++)
    5
    for (int j = i; j <= n; j += i)
    6
    divisors[j].push_back(i);
    7
    }
    8
    9
    int main()
    10
    {
    11
    const int MAXA = 1e6 + 10;
    12
    vector<vector<int>> divisors;
    13
    precomputeDivisors(MAXA, divisors);
    14
    15
    vector<int> cnt(MAXA, 0);
    16
    17
    function<void()> solve = [&]() -> void
    18
    {
    19
    int n, k;
    20
    cin >> n >> k;
    21
    vector<int> arr;
    22
    int cntZero = 0;
    23
    24
    for (int i = 0; i < n; i++)
    25
    {
    26
    int x;
    27
    cin >> x;
    28
    arr.push_back(x);
    29
    if (x == 0) cntZero++;
    30
    }
    31
    32
    if (cntZero >= k)
    33
    {
    34
    cout << "1000000000\n";
    35
    return;
    36
    }
    37
    38
    int maxEle = -1;
    39
    for (int ele : arr)
    40
    for (int div : divisors[ele])
    41
    {
    42
    cnt[div]++;
    43
    if (cnt[div] >= k - cnt[0])
    44
    maxEle = max(maxEle, div);
    45
    }
    46
    47
    cout << maxEle << "\n";
    48
    49
    for (int ele : arr)
    50
    for (int div : divisors[ele])
    51
    cnt[div]--;
    52
    };
    53
    54
    int t;
    55
    cin >> t;
    56
    57
    while (t--)
    58
    solve();
    59
    }
  12. You are given two integer arrays AA and BB of length nn consisiting of non-negative integers. You have to select KK numbers from BB, and then take the bitwise OR of all the elements of AA one at a time with each of the selected elements. The score of this operation is the sum of the nKn \cdot K bitwise OR operations. Find the minimum value of KK such that a score of atleast MM can be achieved.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1M1091 \leq M \leq 10^9
    • 0A[i],B[i]1090 \leq A[i], B[i] \leq 10^9
  13. Increasing Frequency

    Solution
    int maxSubarraySum(vector<int> &arr)
    {
    int n = arr.size();
    int maxSum = 0, sum = 0;
    for (int i = 0; i < n; i++)
    {
    sum = max(arr[i], sum + arr[i]);
    maxSum = max(maxSum, sum);
    }
    return maxSum;
    }
    void solution()
    {
    int n, c;
    cin >> n >> c;
    vector<int> arr(n);
    unordered_map<int, vector<int>> idx;
    for (int i = 0; i < n; i++)
    {
    cin >> arr[i];
    idx[arr[i]].pb(i);
    }
    vector<int> freC(n);
    freC[0] = arr[0] == c;
    for (int i = 1; i < n; i++)
    freC[i] = freC[i - 1] + (arr[i] == c);
    int ans = freC[n - 1];
    for (auto &[ele, id] : idx)
    {
    if (ele == c)
    continue;
    vector<int> arr;
    arr.push_back(1);
    for (int i = 1; i < id.size(); i++)
    {
    int l = id[i - 1], r = id[i];
    arr.push_back(-(freC[r] - freC[l]));
    arr.push_back(1);
    }
    ans = max(ans, freC.back() + maxSubarraySum(arr));
    }
    cout << ans << endl;
    }
  14. You are given three arrays ll, rr and aa, which represents that the ithi^{th} client was making a[i]a[i] requests to the server per second for the duration [l[i],r[i]][l[i], r[i]]. Find the minimum requests per second that this server should be able to handle to serve all the requests.

    Solution

    We can use a line sweep algorithm to solve this problem. We can iterate over all the requests and add the requests to the server at the start time of the request, and remove the requests from the server at the end time of the request. We can then iterate over all the times and calculate the number of requests that the server should be able to handle at that time. The time complexity of the solution is O(nlogn)O(n \log n).

    1
    long long solve(vector<int> a, vector<int> l, vector<int> r)
    2
    {
    3
    using pll = pair<long long, long long>;
    4
    priority_queue<pll, vector<pll>, greater<pll>> pq;
    5
    6
    for (int i = 0; i < a.size(); i++)
    7
    {
    8
    pq.push({l[i], a[i]});
    9
    pq.push({r[i] + 1, -a[i]});
    10
    }
    11
    12
    long long curLoad = 0, maxLoad = 0;
    13
    14
    while (!pq.empty())
    15
    {
    16
    auto [_, load] = pq.top();
    17
    pq.pop();
    18
    19
    curLoad += load;
    20
    maxLoad = max(maxLoad, curLoad);
    21
    }
    22
    23
    return maxLoad;
    24
    }
  15. You are given the initial positions of Alice and Bob as (x1,y1)(x_1, y_1) and (x2,y2)(x_2, y_2). You are also given nn apples at the positions (xi,yi)(x_i, y_i). Alice and Bob need to collect all of the apples in the order they are given. The distance between the two points is the Manhattan distance. Find the minimum distance that Alice and Bob need to travel to collect all the apples.

    Constraints:

    • 1n20001 \leq n \leq 2000
    • 1xi,yi1091 \leq x_i, y_i \leq 10^9
    Solution

    We can use a simple Djikstra to solve this question where the state is represented as (i,j)(i, j), where ii is the index of the apple that Alice is currently at, and jj is the index of the apple that Bob is currently at. The time complexity of the solution is O(n2logn)O(n^2 \log n).

    1
    long long getDis(pair<int, int> a, pair<int, int> b)
    2
    {
    3
    return abs(a.first - b.first) + abs(a.second - b.second);
    4
    }
    5
    6
    void solve()
    7
    {
    8
    int n;
    9
    cin >> n;
    10
    11
    int x1, y1, x2, y2;
    12
    cin >> x1 >> y1 >> x2 >> y2;
    13
    14
    vector<pair<int, int>> apples;
    15
    apples.push_back({x1, y1});
    16
    apples.push_back({x2, y2});
    17
    18
    for (int i = 0; i < n; i++)
    19
    {
    20
    int x, y;
    21
    cin >> x >> y;
    22
    apples.push_back({x, y});
    23
    }
    24
    25
    int m = apples.size();
    26
    27
    vector<vector<long long>> dis(m, vector<long long>(m, 1e18));
    28
    priority_queue<vector<long long>, vector<vector<long long>>, greater<vector<long long>>> pq;
    29
    30
    dis[0][1] = 0;
    31
    pq.push({0, 0, 1});
    32
    33
    while (!pq.empty())
    34
    {
    35
    auto t = pq.top();
    36
    pq.pop();
    37
    38
    int idx1 = t[1], idx2 = t[2];
    39
    long long d = t[0];
    40
    if (dis[idx1][idx2] != d)
    41
    continue;
    42
    43
    if (idx1 == m - 1 || idx2 == m - 1)
    44
    {
    45
    cout << d << endl;
    46
    return;
    47
    }
    48
    49
    int next = max(idx1, idx2) + 1;
    50
    // Move idx1
    51
    if (dis[next][idx2] > d + getDis(apples[idx1], apples[next]))
    52
    {
    53
    dis[next][idx2] = d + getDis(apples[idx1], apples[next]);
    54
    pq.push({dis[next][idx2], next, idx2});
    55
    }
    56
    57
    // Move idx2
    58
    if (dis[idx1][next] > d + getDis(apples[idx2], apples[next]))
    59
    {
    60
    dis[idx1][next] = d + getDis(apples[idx2], apples[next]);
    61
    pq.push({dis[idx1][next], idx1, next});
    62
    }
    63
    }
    64
    65
    cout << -1 << endl;
    66
    }
    67
    68
    int main()
    69
    {
    70
    int TEST_CASES;
    71
    cin >> TEST_CASES;
    72
    while (TEST_CASES--)
    73
    solve();
    74
    return 0;
    75
    }
  16. Count the number of kk periodic subsequences of a string ss of length nn.

    • A string is kk periodic if xi=xi+kx_{i} = x_{i + k} for all valid indexes ii in the string.
    • An empty string is also kk periodic.

    Constraints:

    • 1n201 \leq n \leq 20
    • 1k201 \leq k \leq 20
    Solution

    Since the value of nn is small, we can just generate all the subsequences and check if it is kk periodic. The time complexity of the solution is O(2nk)O(2^n \cdot k).

    int solve(string s, int k) {
    int ans = 0;
    int n = s.size();
    for (int i = 0; i < (1 << n); i++) {
    vector<int> idx;
    for (int j = 0; j < n; j++)
    if ((i >> j) & 1)
    idx.push_back(j);
    bool valid = 1;
    for (int j = 0; j < min((int) idx.size(), k); j++) {
    for (int nxt = j + k; nxt < idx.size(); nxt += k) {
    if (s[idx[j]] != s[idx[nxt]]) {
    valid = 0;
    break;
    }
    }
    }
    ans += valid;
    }
    return ans;
    }
  17. Given an undirected tree with NN nodes such that there exists a path between any two nodes. For the ithi^{th} node, a positive integer value A[i]A[i] is associated with it. You also have a special positive integer KK and you may perform the following operation zero or more times on the given tree: Choose an edge and update the value of the nodes connected with that edge with bitwise XOR of its current value and KK. Formally, A[i]=(A[i]K)A[i] = (A[i] \oplus K) for all ii connected to the chosen edge. Find the maximum value of sumi=1i=NA[i]sum_{i=1}^{i=N} A[i] if you can perform the above operations any number of times.

    Solution

    It can be realized that the structure of the tree does not matter, and the only effective constraint that we have is that we can take the XOR of the nodes with KK in pairs only (you can do so by applying the operation on all the edges in the path between the two chosen nodes). Thus, we can use a simple greedy approach to solve this problem. The time complexity of the solution is O(NlogN)O(N \log N) due to sorting.

    1
    int solve(vector<int> arr, vector<vector<int>> edges, int k)
    2
    {
    3
    vector<int> incr;
    4
    int sum = 0, n = arr.size();
    5
    6
    for (int i = 0; i < arr.size(); i++)
    7
    {
    8
    sum += arr[i];
    9
    incr.push_back((arr[i] ^ k) - arr[i]);
    10
    }
    11
    12
    sort(incr.begin(), incr.end(), greater<int>());
    13
    14
    for (int i = 0; i + 1 < n; i += 2)
    15
    {
    16
    if (incr[i] > 0 && incr[i + 1] > 0)
    17
    {
    18
    sum += incr[i] + incr[i + 1];
    19
    continue;
    20
    }
    21
    22
    if (incr[i] > 0 && incr[i + 1] <= 0)
    23
    {
    24
    if (incr[i] + incr[i + 1] > 0)
    25
    sum += incr[i] + incr[i + 1];
    26
    }
    27
    break;
    28
    }
    29
    30
    return sum;
    31
    }
  18. You are given an array arrarr of nn elements. For each index ii, find the length of the smallest subarray starting at the index ii and having a non-negative sum. If there is no such subarray for an index, set the answer as 00 for that index.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 109arr[i]109-10^9 \leq arr[i] \leq 10^9
    Solution

    We will use a stack to solve this problem. We will iterate over the array from left to right and maintain a stack of indices that have not found a valid subarray for them. Whenever we get an element, if it is non-negative we can set it’s answer as 11 directly and try to pop the elements from the stack that be paired with the current index. If we get a negative element, we will push the index to the stack always.

    We will maintain prefix sums to do this computation in constant time for each index. The time complexity of the solution is O(n)O(n).

    1
    vector<int> solve(vector<int> &arr)
    2
    {
    3
    int n = arr.size();
    4
    5
    vector<long long> pre(n);
    6
    pre[0] = arr[0];
    7
    for (int i = 1; i < n; i++)
    8
    pre[i] = pre[i - 1] + arr[i];
    9
    10
    vector<int> ans(n);
    11
    stack<int> st;
    12
    13
    for (int i = 0; i < n; i++)
    14
    {
    15
    if (arr[i] < 0)
    16
    st.push(i);
    17
    else
    18
    {
    19
    ans[i] = 1;
    20
    while (!st.empty() && pre[i] - (st.top() == 0 ? 0 : pre[st.top() - 1]) >= 0)
    21
    {
    22
    ans[st.top()] = i - st.top() + 1;
    23
    st.pop();
    24
    }
    25
    }
    26
    }
    27
    28
    return ans;
    29
    }
  19. Count Increasing Quadruples

    Solution

    In such questions, often the trick is to fix the middle elements. Thus we will brute force over the pairs of (j,k)(j, k) and then find the number of elements less than arr[k]arr[k] and greater than arr[j]arr[j] in the range [0,j1][0, j - 1] and [k+1,n1][k + 1, n - 1] respectively. Counting the number of elements less than or a greater than a particular number in a range is typically done with a merge sort tree, but since here the elements are given to be in the range [1,n][1, n], we can use simple precomputation to solve the problem. The time complexity of the solution is O(n2)O(n^2).

    1
    class Solution
    2
    {
    3
    public:
    4
    long long countQuadruplets(vector<int> &arr)
    5
    {
    6
    int n = arr.size();
    7
    8
    vector<vector<int>> left(n, vector<int>(n + 1, 0));
    9
    // left[i][j] = Count of numbers <= j till index i
    10
    for (int j = arr[0]; j <= n; j++)
    11
    left[0][j] = 1;
    12
    for (int i = 1; i < n; i++)
    13
    for (int j = 0; j <= n; j++)
    14
    left[i][j] = left[i - 1][j] + (arr[i] <= j);
    15
    16
    vector<vector<int>> right(n, vector<int>(n + 1, 0));
    17
    // right[i][j] = Count of numbers >= j from index [i, n-1]
    18
    for (int j = 0; j <= arr[n - 1]; j++)
    19
    right[n - 1][j] = 1;
    20
    for (int i = n - 2; i >= 0; i--)
    21
    for (int j = 0; j <= n; j++)
    22
    right[i][j] = right[i + 1][j] + (arr[i] >= j);
    23
    24
    long long ans = 0;
    25
    for (int j = 1; j < n - 2; j++)
    26
    for (int k = j + 1; k < n - 1; k++)
    27
    {
    28
    if (arr[k] >= arr[j])
    29
    continue;
    30
    long long l = left[j - 1][arr[k] - 1];
    31
    long long r = arr[j] == n ? 0 : right[k + 1][arr[j] + 1];
    32
    33
    ans += l * r;
    34
    }
    35
    36
    return ans;
    37
    }
    38
    };
  20. You are given a directed tree of nn nodes in the form of an array arrarr such that there is an edge from the node arr[i]arr[i] to the node i+1i + 1 for 1i<n1 \leq i < n. In one operation you can break any edge of this tree, and thus divide the same into two subtrees. Apply this operation repeatedly so that each of the final subtrees is a directed chain, and the total sum of the squares of length of each directed chain is maximized. Return the maximum possible sum of the squares of the lengths of the directed chains. It is gaurenteed that all the nodes are reachable from the root node 11.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    Solution

    It is clear that we should follow a greedy approach where we try to maximise the length of each of the chains. Since the chains are directed, we will intially take the longest paths from the root node to the leaves, and then try to maximise the length of the chains on the other edges. Refer to the following code for the implementation. The time complexity of the solution is O(n)O(n).

    1
    // Returns the maximum depth in the subtree
    2
    // and the rest of the child paths to the paths vector
    3
    int dfs(int u, vector<vector<int>> &g, vector<int> &paths)
    4
    {
    5
    if (g[u].empty())
    6
    return 1;
    7
    8
    vector<int> allDepths;
    9
    for (int v : g[u])
    10
    allDepths.push_back(dfs(v, g, paths));
    11
    12
    sort(allDepths.begin(), allDepths.end(), greater<int>());
    13
    for (int i = 1; i < allDepths.size(); i++)
    14
    paths.push_back(allDepths[i]);
    15
    16
    return 1 + allDepths[0];
    17
    }
    18
    19
    int solve(int n, vector<int> &arr)
    20
    {
    21
    vector<vector<int>> g(n);
    22
    23
    for (int i = 0; i < n - 1; i++)
    24
    g[arr[i] - 1].push_back(i + 1);
    25
    26
    vector<int> paths;
    27
    paths.push_back(dfs(0, g, paths));
    28
    29
    int ans = 0;
    30
    for (int i = 0; i < paths.size(); i++)
    31
    ans += paths[i] * paths[i];
    32
    return ans;
    33
    }
  21. There is an empty container. You want to support 2 types of queries:

    1. 1 V X: Insert an element in the container with value VV and weight XX.
    2. 2 V 0: Let nn be the number of bits in the binary representation of VV. Consider all the elements in the container till now. You need to count the number of elements which when divided by 2i2^i have a remainder of VV, and also return the sum of the weights of these elements.

    Constraints:

    • 1121051 \leq 1 \leq 2 \cdot 10^5
    • If the query is of type 11, then 1V,X1091 \leq V, X \leq 10^9
    • If the query is of type 22, then 1V1091 \leq V \leq 10^9
    Solution

    Since a number upto 10910^9 can have atmost 3030 bits, we can maintain the count of different modulo values and the sum of powers for each possible length of the binary representation of the number. We can use a map to store the count of different modulo values and the sum of weights for each length of the binary representation of the number. The time complexity of the solution is O(30Q)O(30 \cdot Q).

    1
    vector<pair<int, long long>> solve(vector<vector<int>> queries)
    2
    {
    3
    int MAX_BITS = 31;
    4
    vector<unordered_map<int, long long>> powerSum(MAX_BITS), cnt(MAX_BITS);
    5
    6
    vector<pair<int, long long>> ans;
    7
    for (auto q : queries)
    8
    {
    9
    if (q[0] == 1)
    10
    {
    11
    int v = q[1], x = q[2];
    12
    for (int i = 0; i < MAX_BITS; i++)
    13
    {
    14
    int mask = (1 << (i + 1)) - 1;
    15
    powerSum[i][v & mask] += x;
    16
    cnt[i][v & mask]++;
    17
    }
    18
    }
    19
    else
    20
    {
    21
    int v = q[1], v2 = q[1];
    22
    23
    int bitCnt = 0;
    24
    while (v2)
    25
    {
    26
    bitCnt++;
    27
    v2 >>= 1;
    28
    }
    29
    30
    ans.push_back({cnt[bitCnt - 1][v], powerSum[bitCnt - 1][v]});
    31
    }
    32
    }
    33
    34
    return ans;
    35
    }
  22. You are given two binary strings SS and QQ of length nn consisting of only 00 and 11. Consider a non-empty substring S1S_1 of SS and a non-empty substring Q1Q_1 of QQ of the same length. Let XX be the string obtained as the XOR of S1S_1 and Q1Q_1.

    The score of these two strings is defined as floor(len(X)2X10)floor(\frac{len(X)}{2^{X_{10}}}) where X10X_{10} is the decimal representation of XX and len(X)len(X) is the length of the string XX.

    Find the maximum possible score that can be obtained by choosing the strings S1S_1 and Q1Q_1.

    Constraints:

    • 1n1031 \leq n \leq 10^3
    Solution

    The key observation is that since the score is defined as floor(len(X)2X10)floor(\frac{len(X)}{2^{X_{10}}}), the numerator of the fraction can be at max 30003000. To have a non-zero score, the value of 2X102^{X_{10}} must be less than or equal to 30003000, then the value of X10X_{10} must be less than or equal to 1111. Thus, we can be sure that the binary representation of XX will have at most 44 bits (without non-leading zeroes). To compute the number of leading zeroes in the number at every position, we can use a simple precomputation. The time complexity of the solution is O(n2)O(n^2).

    1
    int solve(string &s, string &t)
    2
    {
    3
    int n = s.size();
    4
    5
    // The max common substring of s and t ending at s[i] and t[j]
    6
    // 1 indexed
    7
    vector<vector<int>> maxPre(n + 1, vector<int>(n + 1, 0));
    8
    for (int i = 1; i <= n; i++)
    9
    for (int j = 1; j <= n; j++)
    10
    {
    11
    if (s[i - 1] == t[j - 1])
    12
    maxPre[i][j] = maxPre[i - 1][j - 1] + 1;
    13
    else
    14
    maxPre[i][j] = 0;
    15
    }
    16
    17
    int maxScore = 0;
    18
    for (int lenSub = 1; lenSub <= 4; lenSub++)
    19
    {
    20
    for (int i = 0; i < n - lenSub; i++)
    21
    int a = stoi(s.substr(i, lenSub));
    22
    23
    for (int j = 0; j < n - lenSub; j++)
    24
    {
    25
    int b = stoi(t.substr(j, lenSub));
    26
    int len = lenSub + maxPre[i][j];
    27
    int score = len / (1 << (a ^ b));
    28
    maxScore = max(maxScore, score);
    29
    }
    30
    }
    31
    32
    return maxScore;
    33
    }
  23. You are given an array of length nn, where the ithi^{th} element represents a chocolate of length array[i]array[i]. When you merge two chocolate of lengths xx and yy, cost of merging is x+yx+y, and the resultant chocolate length becomes x+yx+y and is replaced in the array. You need to apply these operations until there is only one chocolate left in the array. Find the minimum cost of merging. The expected time complexity of the algorithm should be O(nlogn)O(n \log n).

  24. You are given two arrays AA and BB of same length nn. You need to find a subset of the indexes [0,1...,n1][0,1..., n-1], such that for any two entries in the subset, say xx and yy the following conditions holds:

    • If A[x]!=A[y]A[x] != A[y] then B[x]!=B[y]B[x] != B[y]
    • If A[x]=A[y]A[x] = A[y] then B[x]=B[y]B[x] = B[y]

    Return the maximum length of the subset possible.

  25. You are given a tree of nn nodes. You are given qq queries where each query has three arguments: node uu, node vv and a number kk. You need to consider the path from uu to vv, and take the XOR of all the nodes in the path and check if it is equal to the given kk. You can exclude atmost one node from the path so that the XOR becomes equal to kk. Return true if the same is possible else false for each query.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1q1051 \leq q \leq 10^5
    • 1k1091 \leq k \leq 10^9
    • 1u,vn1 \leq u, v \leq n
    Solution

    It is clear that if the XOR of the nodes from uu to vv is equal to kk, then we can simply return true. If the same is not true, then we need to check if there is a node xkx \oplus k in the path from uu to vv where \oplus is the XOR operation (as we can exclude this node from the path to get the desried result). To support both of these queries effeciently, we will make use of Mo’s algorithm. The time complexity of the solution is O(nlogn+qn)O(n \log n + q \sqrt{n}).

    An alternative solution for the problem involves the use of Heavy Light Decomposition, but I personally find Mo’s algorithm to be more intuitive and easier to implement in online assessments.

    1
    #include <bits/stdc++.h>
    2
    using namespace std;
    3
    4
    #define IOS \
    5
    ios_base::sync_with_stdio(0); \
    6
    cin.tie(0); \
    7
    cout.tie(0)
    8
    #define INF 1e9
    9
    #define EPS 1e-9
    10
    11
    #define pb push_back
    12
    #define vi vector<int>
    13
    #define vvi vector<vector<int>>
    14
    15
    #define range(x, s, n) for (int x = s; x < n; ++x)
    16
    #define all(a) a.begin(), a.end()
    17
    18
    const int BLOCK_SIZE = 300;
    19
    const int MAXN = 2e5 + 1;
    20
    int nodeFreq[MAXN];
    21
    22
    class Query
    23
    {
    24
    public:
    25
    int l, r, v, c, idx;
    26
    Query(int l, int r, int v, int idx, int c) : l(l), r(r), v(v), c(c), idx(idx) {}
    27
    28
    bool operator<(Query &other) const
    29
    {
    30
    int blk1 = l / BLOCK_SIZE, blk2 = other.l / BLOCK_SIZE;
    31
    if (blk1 != blk2)
    32
    return blk1 < blk2;
    33
    return (blk1 & 1) ? (r > other.r) : (r < other.r);
    34
    }
    35
    };
    36
    37
    class Mo
    38
    {
    39
    int curXor;
    40
    int n;
    41
    42
    public:
    43
    Mo(int n) : n(n)
    44
    {
    45
    curXor = 0;
    46
    range(i, 0, n + 1)
    47
    nodeFreq[i] = 0;
    48
    }
    49
    50
    void add(int idx)
    51
    {
    52
    curXor ^= (idx + 1);
    53
    nodeFreq[idx]++;
    54
    }
    55
    56
    void remove(int idx)
    57
    {
    58
    curXor ^= (idx + 1);
    59
    nodeFreq[idx]--;
    60
    }
    61
    62
    bool check(int val)
    63
    {
    64
    // Either the XOR of the current path is equal to val
    65
    if (curXor == val)
    66
    return true;
    67
    68
    // Or the target is present in the current path
    69
    int tar = curXor ^ val;
    70
    return tar <= n && nodeFreq[tar - 1] == 1;
    71
    }
    72
    73
    bool checkAddNode(int idx, int tar)
    74
    {
    75
    int newCurXor = curXor ^ (idx + 1);
    76
    if (newCurXor == tar)
    77
    return true;
    78
    79
    tar = newCurXor ^ tar;
    80
    return tar <= n && nodeFreq[tar - 1] == 1;
    81
    }
    82
    };
    83
    84
    int main()
    85
    {
    86
    int n, q;
    87
    cin >> n >> q;
    88
    89
    vvi g(n);
    90
    range(i, 0, n - 1)
    91
    {
    92
    int u, v;
    93
    cin >> u >> v;
    94
    u--, v--;
    95
    g[u].pb(v);
    96
    g[v].pb(u);
    97
    }
    98
    99
    int timer = 0;
    100
    vi tin(n), tout(n);
    101
    int l = ceil(log2(n));
    102
    vvi up(n, vi(l + 1));
    103
    vector<int> tour;
    104
    105
    function<void(int, int)> dfs = [&](int u, int p) -> void
    106
    {
    107
    tin[u] = timer++;
    108
    tour.push_back(u);
    109
    110
    up[u][0] = p;
    111
    for (int i = 1; i <= l; i++)
    112
    up[u][i] = up[up[u][i - 1]][i - 1];
    113
    114
    for (int v : g[u])
    115
    {
    116
    if (v == p)
    117
    continue;
    118
    dfs(v, u);
    119
    }
    120
    121
    tout[u] = timer++;
    122
    tour.push_back(u);
    123
    };
    124
    dfs(0, 0);
    125
    126
    auto isAncestor = [&](int u, int v) -> bool
    127
    {
    128
    return tin[u] <= tin[v] && tout[u] >= tout[v];
    129
    };
    130
    131
    auto getLCA = [&](int u, int v) -> int
    132
    {
    133
    if (isAncestor(u, v))
    134
    return u;
    135
    if (isAncestor(v, u))
    136
    return v;
    137
    138
    for (int i = l; i >= 0; i--)
    139
    if (!isAncestor(up[u][i], v))
    140
    u = up[u][i];
    141
    142
    return up[u][0];
    143
    };
    144
    145
    vector<Query> qu;
    146
    for (int i = 0; i < q; i++)
    147
    {
    148
    int u, v, val;
    149
    scanf("%d %d %d", &u, &v, &val);
    150
    u--, v--;
    151
    152
    if (tin[u] > tin[v])
    153
    swap(u, v);
    154
    int lca = getLCA(u, v);
    155
    if (lca == u)
    156
    qu.push_back(Query(tin[u], tin[v], val, i, -1));
    157
    else
    158
    qu.push_back(Query(tout[u], tin[v], val, i, lca));
    159
    }
    160
    161
    sort(all(qu));
    162
    vector<int> ans(q);
    163
    Mo mo(n);
    164
    165
    int curL = 0,
    166
    curR = -1;
    167
    for (auto &q : qu)
    168
    {
    169
    while (curL > q.l)
    170
    {
    171
    curL--;
    172
    mo.add(tour[curL]);
    173
    }
    174
    while (curR < q.r)
    175
    {
    176
    curR++;
    177
    mo.add(tour[curR]);
    178
    }
    179
    while (curL < q.l)
    180
    {
    181
    mo.remove(tour[curL]);
    182
    curL++;
    183
    }
    184
    while (curR > q.r)
    185
    {
    186
    mo.remove(tour[curR]);
    187
    curR--;
    188
    }
    189
    190
    ans[q.idx] = mo.check(q.v);
    191
    if (q.c != -1)
    192
    {
    193
    int leftNode = tour[tin[q.c]];
    194
    ans[q.idx] |= mo.checkAddNode(leftNode, q.v);
    195
    }
    196
    }
    197
    198
    for (int x : ans)
    199
    cout << (x ? "true" : "false") << endl;
    200
    }

Online Assessment Questions

  1. You are given a string ss and an arrarr of integers, both of length nn. You can swap indexes ii and jj of the string ss if arr[i]=arr[j]arr[i] = arr[j]. Find the lexographically smallest string ss you can obtain after performing some (possible zero) swaps.

    • 1n1051 \leq n \leq 10^5
  2. There are nn types of objects, and each has a cost denoted by arr[n]arr[n]. In some operations, you can either:

    • Choose an index ii, pay arr[i]arr[i] and get 11 object of type ii.
    • Pay cost xx, and transform all the objects of type ii to type i+1i + 1. The object of type nn is converted to type 11. The cost of the objects is only related to their index and not their type.

    Find the minimum cost to get 11 object of each type.

    • 1n1031 \leq n \leq 10^3
    • 1arr[i]1091 \leq arr[i] \leq 10^9
    • 1x1091 \leq x \leq 10^9
    Solution

    Suppose that you perform the second operation kk times. Then you would need to add the fixed cost kxk \cdot x to the total cost. After that, for each object of type ii, you would be able to buy it in the minimum of the cost in the range arr[i]arr[i] to arr[i+k]arr[i + k]. Thus loop over the number of times you perform the second operation and find the minimum cost using sliding windows for each object of type ii. If you use a set with the sliding window, the complexity is O(n2logn)O(n^2 \log n) which passed comfortably.

  3. You are given an array of strings arrarr. A permuation of the arrarr is called valid if for any two strings in the array that have a common prefix, all the strings between them also have atleast that common prefix. For example, the ordering [a, aa, aab] and [a, aab, aa] are both valid, but [hi, ho, hi] is not. Find the number of valid permutations of the array.

    • 1n1031 \leq n \leq 10^3

    • 1arr[i].size()1031 \leq arr[i].size() \leq 10^3

    • Example #1 For the array ["a", "aa", "aaa", "aaaa"], the answer is 88.

    • Example #2 For the array ["ivo", "ja", "jo"], the answer is 44.

    Solution

    This question can be solved with the help of a trie. Each prefix of a word denotes a split point, where all the next nodes can be arranged in any specific order. We would also need to add an extra dummy character to denote the end of the word. In the OA, when using pointers to allocate the memory for nodes of the trie, a MLE verdict was given. Thus, we need to use a vector of nodes to store the trie nodes. The time complexity of the solution is O(nm)O(n \cdot m) where mm is the maximum length of the string.

    1
    long long mod = 1e9 + 7;
    2
    vector<long long> fac;
    3
    4
    class Node
    5
    {
    6
    public:
    7
    vector<int> ch;
    8
    9
    Node() : ch(vector<int>(27, -1)) {}
    10
    };
    11
    12
    class Trie
    13
    {
    14
    vector<Node> nodes;
    15
    16
    public:
    17
    Trie()
    18
    {
    19
    nodes.clear();
    20
    nodes.emplace_back(Node());
    21
    }
    22
    23
    void insert(string &s)
    24
    {
    25
    s += 'z' + 1;
    26
    int cur = 0;
    27
    for (char ch : s)
    28
    {
    29
    int childIdx = ch - 'a';
    30
    if (nodes[cur].ch[childIdx] == -1)
    31
    {
    32
    nodes[cur].ch[childIdx] = nodes.size();
    33
    nodes.emplace_back(Node());
    34
    }
    35
    cur = nodes[cur].ch[childIdx];
    36
    }
    37
    }
    38
    39
    long long dfs(int nodeIdx)
    40
    {
    41
    long long ans = 1;
    42
    int cnt = 0;
    43
    44
    for (int i = 0; i < 27; i++)
    45
    {
    46
    if (nodes[nodeIdx].ch[i] == -1)
    47
    continue;
    48
    cnt++;
    49
    ans *= dfs(nodes[nodeIdx].ch[i]);
    50
    ans %= mod;
    51
    }
    52
    53
    ans *= fac[cnt];
    54
    ans %= mod;
    55
    56
    return ans;
    57
    }
    58
    };
    59
    60
    int solve(vector<string> &words)
    61
    {
    62
    fac.resize(30);
    63
    fac[0] = 1;
    64
    for (int i = 1; i < 30; i++)
    65
    fac[i] = (fac[i - 1] * i) % mod;
    66
    67
    Trie trie;
    68
    for (string &s : words)
    69
    trie.insert(s);
    70
    71
    return trie.dfs(0);
    72
    }

26 Miles Capital

There were 2020 questions in the test, which had to be solved in 6060 minutes. Out of the same, 22 were coding questions which were different for each candidate. The rest of the questions were MCQs from the topics of finance, probablity, data interpretation, and logical reasoning. The MCQs were also shuffled between the candidates.

Coding Questions

  1. Find all the distinct palindromic substrings of the given string ss. The length of ss is upto 51035 \cdot 10^3.

    Solution

    You can fix the center of the palindrome, and then iterate creating odd and even length palindromes from that center. The time complexity of the solution is O(n2)O(n^2). To find the unique palindromes, you can use rolling hash to convert all the substrings to a number in constant time and push them to a set, thus adding an additonal O(logn)O(\log n) factor to the runtime. As luck would have it, the test cases of the questions were weak, and a O(n3)O(n^3) solution where I generated the substring between the two indexes and then pushed it to a set passed the test cases.

  2. Count paths that can form a palindrome in a tree

  3. You are given an unidirected tree of nn nodes, where each node has a value arr[i]arr[i] which is rooted at node 11. In one operation, you can select a node and delete the entire subtree of that node (along with it). The cost of one such operation is xx. The final score of the tree is the sum of the values in the tree after all the operations minus the total cost of the operations. What is the maximum possible score that can be obtained?

    • 1n1051 \leq n \leq 10^5
    • 109arr[i]109-10^9 \leq arr[i] \leq 10^9
    • 1x1091 \leq x \leq 10^9
  4. You are given a string ss that contains spaces, commas, brackets, 00, 11 and logical operators such as &, | and !. The string given will always represent a valid boolean expression in prefix notation, and would be bracketted appropriately to convey the precedence. Find the value of the boolean expression.

    • Example: | [& [! 1] 0 [! [! 0]]] [& 0 0] would evaluate to 0.

ThoughtSpot

Other Campus Questions

  1. Count the Number of Palindromic Paths in a Tree

    Solution
    1
    class Solution {
    2
    public:
    3
    long long countPalindromePaths(vector<int>& parent, string s) {
    4
    int n = parent.size();
    5
    vector<vector<pair<int, char>>> g(n);
    6
    for (int i = 1; i < n; i++)
    7
    g[parent[i]].push_back({i, s[i]});
    8
    9
    map<int, long long> cnt;
    10
    function<void(int, int)> dfs = [&](int u, int m) -> void {
    11
    cnt[m]++;
    12
    for (auto [v, c]: g[u]) {
    13
    int newMask = m ^ (1 << (c - 'a'));
    14
    dfs(v, newMask);
    15
    }
    16
    };
    17
    dfs(0, 0);
    18
    19
    long long ans = 0;
    20
    for (auto [m, f]: cnt) {
    21
    ans += f * (f - 1);
    22
    for (int i = 0; i < 26; i++)
    23
    if (cnt.find(m ^ (1 << i)) != cnt.end())
    24
    ans += f * cnt[m ^ (1 << i)];
    25
    }
    26
    27
    return ans / 2;
    28
    }
    29
    };
  2. Determine the number of integers in the range (l,r)(l, r) such that they have no repeating digits. Each test file has qq queries.

    Constraints:

    • 1q1051 \leq q \leq 10^5
    • 1l,r1061 \leq l, r \leq 10^6
  3. Given two integers (l,r)(l, r), determine the number of integers in the range (l,r)(l, r) such that they are a power number. A power number xx is a number that can be expressed as x=ap+bqx = a^p + b^q where a,b,p,qa, b, p, q are positive integers and p,q>1p, q > 1 and a,b>0a, b > 0.

    Constraints:

    • 1l,r51061 \leq l, r \leq 5 \cdot 10^6
    Solution
    1
    int main()
    2
    {
    3
    long long l, r;
    4
    cin >> l >> r;
    5
    6
    vector<long long> isPow(r + 1, 0);
    7
    isPow[0] = isPow[1] = 1;
    8
    for (long long i = 2; i * i <= r; i++)
    9
    {
    10
    long long j = i * i;
    11
    while (j <= r)
    12
    {
    13
    isPow[j] = 1;
    14
    j *= i;
    15
    }
    16
    }
    17
    18
    vector<int> pow;
    19
    for (int i = 0; i <= r; i++)
    20
    if (isPow[i])
    21
    pow.push_back(i);
    22
    23
    vector<long long> isGood(r + 1, 0);
    24
    for (int i = 0; i < pow.size(); i++)
    25
    for (int j = i; j < pow.size(); j++)
    26
    {
    27
    if (pow[i] + pow[j] > r)
    28
    break;
    29
    isGood[pow[i] + pow[j]] = 1;
    30
    }
    31
    32
    int cnt = 0;
    33
    for (int i = l; i <= r; i++)
    34
    cnt += isGood[i];
    35
    cout << cnt << "\n";
    36
    }
  4. Minimum Swaps to Make the String Balanced

    Solution
    1
    class Solution {
    2
    public:
    3
    int minSwaps(string s) {
    4
    int n = s.size();
    5
    int j = n - 1, bal = 0, ans = 0;
    6
    7
    for (int i = 0; i < n; i++) {
    8
    if (s[i] == '[')
    9
    bal++;
    10
    else if (bal > 0)
    11
    bal--;
    12
    else {
    13
    while (s[j] != '[')
    14
    j--;
    15
    swap(s[i], s[j]);
    16
    ans++;
    17
    bal++;
    18
    }
    19
    }
    20
    21
    return ans;
    22
    }
    23
    };
  5. The office manager of a healthcare billing company has been charged with eliminating food waste in the office lounge. The lounge has packets of coffee creamer, each with an expiry date. The creamer must be used no later than that day. The manager also has the option to order additional coffee creamer from a grocery store, each with varying expiry dates. Given a fixed daily demand for creamer, find the maximum amount of additional creamer the manager can order without waste.

    Example:

    onHand[0, 2, 2]
    supplier = [2, 0, 0]
    demand = 2
    The lounge has 3 units on hand expiring in [0,2,2] days, respectively.
    The store has an additional 3 units available, expiring in [2,0,0] days.
    Employees use at most 2 units of coffee creamer per day.
    The manager can order a maximum of 2 units: the one expiring in 2 days, and one in 0 days.
    The creamer can then be used as follows:
    Day 0 -> onHand[0] and supplier[1]
    Day 1 -> onHand[1] and supplier[0]
    Day 2 -> onHand[2]

    Constraints:

    • 1n,m1051 \leq n, m \leq 10^5
    • 1demand1051 \leq demand \leq 10^5
    Solution
    1
    int main()
    2
    {
    3
    int n;
    4
    cin >> n;
    5
    map<int, int> inHand;
    6
    for (int i = 0; i < n; i++)
    7
    {
    8
    int x;
    9
    cin >> x;
    10
    inHand[x]++;
    11
    }
    12
    13
    int m;
    14
    cin >> m;
    15
    map<int, int> add;
    16
    for (int i = 0; i < m; i++)
    17
    {
    18
    int x;
    19
    cin >> x;
    20
    add[x]++;
    21
    }
    22
    23
    int dem;
    24
    cin >> dem;
    25
    26
    auto check = [&](int units) -> bool
    27
    {
    28
    map<int, int> have = inHand;
    29
    30
    for (auto itr = add.rbegin(); itr != add.rend(); itr++)
    31
    {
    32
    auto &[exp, cnt] = *itr;
    33
    int qty = min(units, cnt);
    34
    have[exp] += qty;
    35
    units -= qty;
    36
    if (units == 0)
    37
    break;
    38
    }
    39
    40
    int day = 0, need = dem;
    41
    for (auto itr = have.begin(); itr != have.end();)
    42
    {
    43
    auto [exp, cnt] = *itr;
    44
    if (exp < day)
    45
    return 0;
    46
    47
    int qty = min(cnt, need);
    48
    need -= qty;
    49
    if (need == 0)
    50
    {
    51
    day++;
    52
    need = dem;
    53
    }
    54
    55
    if (cnt == qty)
    56
    itr++;
    57
    else
    58
    (*itr).second -= qty;
    59
    }
    60
    61
    return 1;
    62
    };
    63
    64
    int l = 0, r = m;
    65
    int ans = -1;
    66
    while (l <= r)
    67
    {
    68
    int mid = (l + r) / 2;
    69
    if (check(mid))
    70
    {
    71
    ans = mid;
    72
    l = mid + 1;
    73
    }
    74
    else
    75
    r = mid - 1;
    76
    }
    77
    78
    cout << ans << "\n";
    79
    }
  6. There are in processes to be executed, and the ithi^th process has a size of processSize[i]processSize[i]. Also, there are mm processors of different size capacity. The capacity of the processor is capacity[i]capacity[i]. A processor can process a task of size less than or equal to it’s capacity in 11 second, but it can not execute processes whose size is greater than it’s capacity. A processor can execute multiple processes one after the other, but needs to pause for 11 second after completing it’s current one. Multiple processors can work on different processes simultaneously. Find the minimum time to execute all the processes or return 1-1 if there is no way to execute all the processes.

    Constraints:

    • 1n,m1051 \leq n, m \leq 10^5
    • 1processSize[i],capacity[i]1091 \leq processSize[i], capacity[i] \leq 10^9
    Solution
    1
    int main()
    2
    {
    3
    int n;
    4
    cin >> n;
    5
    vector<int> p(n);
    6
    for (int i = 0; i < n; i++)
    7
    cin >> p[i];
    8
    sort(p.begin(), p.end(), greater<int>());
    9
    10
    int m;
    11
    cin >> m;
    12
    vector<int> cap(m);
    13
    for (int i = 0; i < m; i++)
    14
    cin >> cap[i];
    15
    sort(cap.begin(), cap.end(), greater<int>());
    16
    17
    auto check = [&](int mxTime) -> bool
    18
    {
    19
    int canProcess = (mxTime + 1) / 2;
    20
    int toProcess = 0;
    21
    22
    for (int i = 0; i < m; i++)
    23
    {
    24
    int done = 0;
    25
    while (toProcess < n && done < canProcess && p[toProcess] <= cap[i])
    26
    {
    27
    done++;
    28
    toProcess++;
    29
    }
    30
    }
    31
    32
    return toProcess == n;
    33
    };
    34
    35
    int l = 0, r = 1e9;
    36
    int ans = -1;
    37
    while (l <= r)
    38
    {
    39
    int mid = (l + r) / 2;
    40
    if (check(mid))
    41
    {
    42
    ans = mid;
    43
    r = mid - 1;
    44
    }
    45
    else
    46
    l = mid + 1;
    47
    }
    48
    49
    cout << ans << "\n";
    50
    }
  7. Two strings are given, wordword and substrsubstr. Some of the characters in word are a question mark (?). Find the lexicographically smallest string that can be obtained by replacing ? characters such that substrsubstr appears at least once. If it is not possible to do so, return “-1”.

    Constraints:

    • 1word,substr1031 \leq |word|, |substr| \leq 10^3
    • wordword and substrsubstr contain only lowercase English letters and ?
    Solution
    1
    int main()
    2
    {
    3
    string s, p;
    4
    cin >> s >> p;
    5
    int n = s.size(), m = p.size();
    6
    7
    vector<vector<int>> dp(n, vector<int>(m, -1));
    8
    9
    function<bool(int, int)> poss = [&](int idx, int matIdx) -> bool
    10
    {
    11
    if (matIdx == m)
    12
    return 1;
    13
    if (idx == n)
    14
    return 0;
    15
    if (dp[idx][matIdx] != -1)
    16
    return dp[idx][matIdx];
    17
    18
    if (s[idx] != '?')
    19
    return dp[idx][matIdx] = poss(idx + 1, s[idx] == p[matIdx] ? matIdx + 1 : 0);
    20
    21
    // Try replacing with 'a'
    22
    if (poss(idx + 1, p[0] == 'a'))
    23
    {
    24
    s[idx] = 'a';
    25
    return dp[idx][matIdx] = 1;
    26
    }
    27
    28
    // Try replacing with the character from pattern
    29
    if (poss(idx + 1, matIdx + 1))
    30
    {
    31
    s[idx] = p[matIdx];
    32
    return dp[idx][matIdx] = 1;
    33
    }
    34
    35
    return dp[idx][matIdx] = 0;
    36
    };
    37
    38
    if (!poss(0, 0))
    39
    {
    40
    cout << "-1";
    41
    return 0;
    42
    }
    43
    44
    for (auto &ch : s)
    45
    if (ch == '?')
    46
    ch = 'a';
    47
    cout << s << "\n";
    48
    49
    return 0;
    50
    }

    Additional Follow Up: Can you solve this problem in the same constraints if the same was asked for the pattern to appear as a subsequence in the string?

  8. You are given a tree with nn nodes. Each node has a value denoted by arr[i]arr[i]. Consider all the simple paths in the tree, and return the maximum possible sum of the values of the nodes lying on any path on the tree.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 109arr[i]109-10^9 \leq arr[i] \leq 10^9
    Solution
    1
    void solve()
    2
    {
    3
    int n;
    4
    cin >> n;
    5
    6
    vector<long long> arr(n);
    7
    for (int i = 0; i < n; i++)
    8
    cin >> arr[i];
    9
    10
    vector<vector<int>> g(n);
    11
    for (int i = 0; i < n - 1; i++)
    12
    {
    13
    int u, v;
    14
    cin >> u >> v;
    15
    g[u - 1].push_back(v - 1);
    16
    g[v - 1].push_back(u - 1);
    17
    }
    18
    19
    vector<long long> mxDown(n);
    20
    21
    long long ans = -1e18;
    22
    function<void(int, int)> dfs = [&](int u, int p) -> void
    23
    {
    24
    long long mx1 = 0, mx2 = 0;
    25
    26
    for (int v : g[u])
    27
    {
    28
    if (v == p)
    29
    continue;
    30
    dfs(v, u);
    31
    if (mxDown[v] >= mx1)
    32
    {
    33
    mx2 = mx1;
    34
    mx1 = mxDown[v];
    35
    }
    36
    else if (mxDown[v] > mx2)
    37
    mx2 = mxDown[v];
    38
    }
    39
    40
    mxDown[u] = arr[u] + mx1;
    41
    ans = max(ans, mx1 + mx2 + arr[u]);
    42
    };
    43
    dfs(0, -1);
    44
    45
    cout << ans << "\n";
    46
    }
    47
    48
    int main()
    49
    {
    50
    int t;
    51
    cin >> t;
    52
    while (t--)
    53
    solve();
    54
    }
  9. There is a tree with nn nodes. The tree is rooted at node with number 00. As usually in computer science, the tree grows upside down comparing to trees existing in nature. Apples grow on nodes of this tree. Some of these apples are underhydrated, some are overhydrated, and others are neither. You know that for each overhydrated apple you’ll get aa cents penalty and for every underhydrated you’ll get bb cents penalty. Now, you want to pour water on exactly one node of the tree. When you pour water on node all apples that are in node’s subtree, i.e., itself and all descendants of the node will be hydrated and in consequence, each hydrated apple that was almost overhydrated becomes overhydrated. Moreover, every apple in the whole tree that was almost underhydrated and no water was poured on it gets underhydrated. Calculate the minimum total penalty you can get from pouring water on exactly one node of the tree.

    You are given:

    • An integer array, parpar of size nn where par[i]par[i] denotes the parent of the ithi^{th} node.
    • An integer array, arrarr of size nn where arr[i]arr[i], denotes the level of the water in the apple on node. It’s either 1-1, 00 or 11, where 1-1 stands for almost underhydrated, 00 stands for neither and 11 stands for almost overhydrated.
    • Integers aa and bb denoting the penalty for overhydrated and underhydrated apples respectively.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1a,b1091 \leq a, b \leq 10^9
    Solution
    1
    int solve(vector<int> &par, vector<int> &arr, int a, int b) {
    2
    int n = par.size();
    3
    4
    vector<vector<int>> g(n);
    5
    for (int i = 1; i < n; i++) {
    6
    g[par[i]].push_back(i);
    7
    }
    8
    9
    vector<vector<int>> cnt(n, vector<int>(3));
    10
    11
    function<void(int, int)> dfs = [&](int u, int p) -> void {
    12
    cnt[u][arr[u] + 1]++;
    13
    for (int v : g[u]) {
    14
    if (v == p) continue;
    15
    dfs(v, u);
    16
    for (int i = 0; i < 3; i++)
    17
    cnt[u][i] += cnt[v][i];
    18
    }
    19
    };
    20
    dfs(0, -1);
    21
    22
    int ans = 1e9;
    23
    int totUnder = cnt[0][0];
    24
    for (int i = 0; i < n; i++) {
    25
    int over = cnt[i][2];
    26
    int under = totUnder - cnt[i][0];
    27
    ans = min(ans, over * a + under * b);
    28
    }
    29
    30
    return ans;
    31
    }
  10. You are given nn items, each characterized by three values (ty,w,v)(ty, w, v), where tyty is the type number of the item, ww is the weight of the item and vv is the value of the item. You can carry atmost a weight of kk. Determine the maximum value of the items you can carry subject to the condition that you can not take two items of the same type together.

    Constraints:

    • 1n,k,ty,w,v1031 \leq n, k, ty, w, v \leq 10^3
    Solution
    1
    int main()
    2
    {
    3
    int n;
    4
    cin >> n;
    5
    6
    vector<vector<int>> arr(n, vector<int>(3));
    7
    for (int i = 0; i < n; i++)
    8
    for (int j = 0; j < 3; j++)
    9
    cin >> arr[i][j];
    10
    11
    sort(arr.begin(), arr.end());
    12
    vector<int> nxt(n);
    13
    for (int i = n - 1; i >= 0; i--)
    14
    {
    15
    int end = i + 1;
    16
    while (i - 1 >= 0 && arr[i - 1][0] == arr[i][0])
    17
    i--;
    18
    for (int j = i; j < end; j++)
    19
    nxt[j] = end;
    20
    }
    21
    22
    int k;
    23
    cin >> k;
    24
    25
    vector<vector<int>> dp(n, vector<int>(k + 1, -1));
    26
    27
    function<int(int, int)> get = [&](int idx, int wt) -> int
    28
    {
    29
    if (idx == n)
    30
    return 0;
    31
    if (dp[idx][wt] != -1)
    32
    return dp[idx][wt];
    33
    34
    int ans = get(idx + 1, wt);
    35
    if (arr[idx][1] + wt <= k)
    36
    {
    37
    int nxtIdx = nxt[idx];
    38
    ans = max(ans, arr[idx][2] + get(nxtIdx, arr[idx][1] + wt));
    39
    }
    40
    41
    return dp[idx][wt] = ans;
    42
    };
    43
    44
    cout << get(0, 0) << "\n";
    45
    }

Online Assessment Questions

  1. Avoid Straight Line

    Solution
    #include <bits/stdc++.h>
    using namespace std;
    #define IOS \
    ios_base::sync_with_stdio(0); \
    cin.tie(0); \
    cout.tie(0)
    #define INF 1e9
    #define EPS 1e-9
    #define pb push_back
    #define ll long long int
    #define dbl long double
    #define vi vector<int>
    #define vvi vector<vector<int>>
    #define vll vector<long long int>
    #define vvll vector<vector<long long int>>
    #define pii pair<int, int>
    #define pll pair<long long int, long long int>
    #define vpii vector<pair<int, int>>
    #define vvpii vector<vector<pair<int, int>>>
    #define vpll vector<pair<long long int, long long int>>
    #define range(x, s, n) for (int x = s; x < n; ++x)
    #define all(a) a.begin(), a.end()
    void solution();
    const int MOD = 1e9 + 7;
    int main()
    {
    IOS;
    int TEST_CASES;
    TEST_CASES = 1;
    while (TEST_CASES--)
    solution();
    return 0;
    }
    void solution()
    {
    int n;
    cin >> n;
    vvi g(n);
    range(i, 0, n - 1)
    {
    int u, v;
    cin >> u >> v;
    g[u - 1].pb(v - 1);
    g[v - 1].pb(u - 1);
    }
    vll sub(n);
    ll ans = 0;
    auto get = [](vll &a) -> ll
    {
    ll s1 = 0, s2 = 0, s3 = 0;
    for (auto a : a)
    {
    s3 += s2 * a;
    s2 += s1 * a;
    s1 += a;
    }
    return s3;
    };
    function<void(int, int)> dfs = [&](int u, int p) -> void
    {
    sub[u] = 1;
    vll comp;
    for (int v : g[u])
    {
    if (v == p)
    continue;
    dfs(v, u);
    sub[u] += sub[v];
    comp.pb(sub[v]);
    }
    comp.pb(n - sub[u]);
    ans += get(comp);
    };
    dfs(0, -1);
    cout << ans << "\n";
    }
  2. You are given a weighted undirected tree of nn nodes. A pair of nodes (x,y)(x, y) can communicate via a third node zz if and only if the distance of xx and zz and the the distance of yy to zz are both divisible the by the given constant ww. For each node, calculate the number of pairs of nodes that can communicate via it.

    Constraints:

    • 1n10001 \leq n \leq 1000
    • 1w1041 \leq w \leq 10^4
  3. You need to implement a text editor. Intially the string on the screen is empty, and the cursor is at the 0th0^{th} position. Next the following type of queries would be made to the same:

    1. insert s: Insert the string ss at the current cursor position. The cursor moves to the end of the inserted string.
    2. print x: If the cursor is at the mthm^{th} position, print the characters in the range [mx,m+x][m - x, m + x].
    3. left x: Move the cursor xx positions to the left.
    4. right x: Move the cursor xx positions to the right.
    5. backscape x: Delete the last xx characters from the screen with respect to the cursor position.
    6. delete x: Delete the next xx characters from the screen with respect to the cursor position.

    All the cursor positions may go out of bounds. You must handle them as any regular text editor would. It is given that the number of queries would be at most 50005000 and the length of the intermediate text on the screen would never exceed 125125 characters.


Alphonso

Other Campus Questions

  1. You are given a tree with nn nodes and a number mm. The tree is rooted at 11. You need to assign each node a value in the range 11 to mm. The so formed tree is called beautiful if the GCD of the values on the path from the root to atleast one leaf node is greater than 11. Find the number of beautiful trees. Output the same modulo 109+710^9 + 7.

    Solution
    1
    long long MOD = 1e9 + 7;
    2
    3
    long long dfs(int u, int p, int curG, vector<vector<int>> &g, vector<vector<long long>> &dp, int m)
    4
    {
    5
    if (dp[u][curG] != -1)
    6
    return dp[u][curG];
    7
    8
    if (g[u].size() == 1 && g[u][0] == p)
    9
    {
    10
    int cnt = 0;
    11
    for (int i = 1; i <= m; i++)
    12
    if (__gcd(i, curG) == 1)
    13
    cnt++;
    14
    return dp[u][curG] = cnt;
    15
    }
    16
    17
    long long ans = 1;
    18
    for (int myVal = 1; myVal <= m; myVal++)
    19
    {
    20
    long long cur = 1;
    21
    int newG = __gcd(curG, myVal);
    22
    for (int v : g[u])
    23
    {
    24
    if (v == p)
    25
    continue;
    26
    cur *= dfs(v, u, newG, g, dp, m);
    27
    cur %= MOD;
    28
    }
    29
    ans += cur;
    30
    ans %= MOD;
    31
    }
    32
    33
    return dp[u][curG] = ans;
    34
    }
    35
    36
    long long binPower(long long a, long long b)
    37
    {
    38
    long long res = 1;
    39
    while (b)
    40
    {
    41
    if (b & 1)
    42
    {
    43
    res *= a;
    44
    res %= MOD;
    45
    }
    46
    a *= a;
    47
    a %= MOD;
    48
    b >>= 1;
    49
    }
    50
    return res;
    51
    }
    52
    53
    int main()
    54
    {
    55
    int n, m;
    56
    cin >> n >> m;
    57
    58
    vector<vector<int>> g(n);
    59
    for (int i = 0; i < n - 1; i++)
    60
    {
    61
    int u, v;
    62
    cin >> u >> v;
    63
    g[u - 1].push_back(v - 1);
    64
    g[v - 1].push_back(u - 1);
    65
    }
    66
    67
    vector<vector<long long>> dp(n, vector<long long>(m + 1, -1));
    68
    69
    long long ans = binPower(n, m) - dfs(0, -1, 0, g, dp, m);
    70
    ans = (ans + MOD) % MOD;
    71
    cout << ans << "\n";
    72
    }

Online Assessment Questions

  1. You are given a binary tree with nn nodes. You need to answer qq on the same. Each query involves remvoing the subtree of the node q[i]q[i] and then finding the maximum value present in the tree. Output the same for each query. All the queries are independent of each other, and thus the tree restores to the original state after each query.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1q1051 \leq q \leq 10^5
  2. You are given an array of nn integers. You want to change the array so that all the elements in the array are unique, and when the array is sorted, the element are consequtive integers. In one operation, you can change any one element of the array to any value that you want. Output the minimum number of operations required to make the array unique and sorted.

    Constraints:

    • 1n1051 \leq n \leq 10^5
    • 1ai1091 \leq a_i \leq 10^9
  3. You are given mm boxes of the form [si,ti][s_i, t_i] where sis_i is the size of the box, and tit_i is the type of the box. You are also given nn items, each of the form [si,ti][s_i, t_i]. You are pack an item in a box only if the sizes of the box and item are equal. The packing is called optimal if the type of the box and the item are equal as well. You need to find the maximum number of items that can be packed, and how many of these items can be packed optimally.

    Constraints:

    • 1n,m1051 \leq n, m \leq 10^5
    • 1si,ti1091 \leq s_i, t_i \leq 10^9