CSES Solutions - Collecting Numbers II
Last Updated :
15 Apr, 2024
Given an array that contains each number between 1 to n exactly once. Your task is to collect the numbers from 1 to n in increasing order. On each round, you go through the array from left to right and collect as many numbers as possible. Given m operations that swap two numbers in the array, your task is to report the number of rounds after each operation.
Examples:
Input: n = 5, m = 3, values[] = {4, 2, 1, 5, 3}, swaps[][] = {{2, 3}, {1, 5}, {2,3}}
Output:
2
3
4
Explanation:
- In the 1st operation after swapping the values of 2nd and 3rd position the array is {4, 1, 2, 5, 3}. We can collect 1, 2, 3 in the 1st round and 4, 5 in the 2nd round. Hence, the answer is 2.
- In the 2nd operation after swapping the values of 1st and 5th position the array is {3, 1, 2, 5, 4}. We can collect 1, 2 in the 1st round, 3, 4 in the 2nd round and 5 in the 3rd round. Hence, the answer is 3.
- In the 3rd operation after swapping the values of 2nd and 3rd position the array is {3, 2, 1, 5, 4}. We can collect 1 in the 1st round, 2 in the 2nd round, 3, 4 in the 3rd round and 5 in the 4th round. Hence, the answer is 4.
Input: n = 4, m = 1, values[] = {4, 2, 3, 1}, swaps[][] = {{1, 4}}
Output: 1
Explanation: After the first swap operation, the array will be {1, 2, 3, 4}. We can collect 1, 2, 3 and 4 in the first round only.
Approach: To solve the problem, follow the idea below:
The idea is to calculate the number of inversions, where values[i] > values[j] and position[i] < position[j], between adjacent elements. This will give us the number of rounds required to collect all numbers from 1 to n in the given order. Count the number of inversions formed by given order of elements. Begin the operation. Since only the adjacent elements (the previous and next element of the current element) are affected, we store them in a set if they exist. Then subtract from the count, the inversions formed by our current set as there may be some elements that don’t form an inversion after the swap and if they form they'll be counted. Next, we swap the elements, update the positions, and again count and add the inversions by adjacent elements to our existing count. This approach reduces the time complexity by checking only the neighboring elements.
Step-by-step algorithm:
- Create a vector to store the positions of each value in the array.
- Initialize a count variable to 1.
- Iterate over the array from 1 to n-1.
- If there is an inversion i.e. the position of the current value is greater than the position of the next value, increment the count.
- Declare a set to store the pairs of values that will be updated in each swap operation.
- Update the count before the swap, subtract from the count, the inversions formed by our current set as there may be some elements that don’t form an inversion after the swap and if they form they'll be counted.
- Swap the values at the given positions.
- Update the positions of the swapped values.
- Count and add the inversions by adjacent elements to our existing count.
- Add the count to the result vector.
- Clear the set for the next operation.
- Return the result.
Below is the implementation of the algorithm:
C++
// C++ code
#include <bits/stdc++.h>
using namespace std;
vector<int>
collectingnumbersII(int n, int m, vector<int>& values,
vector<vector<int> >& swaps)
{
// Make the array 1-indexed
values.insert(values.begin(), 0);
vector<int> res;
vector<int> position(n + 1);
// Store the positions of the values
for (int i = 1; i <= n; i++)
position[values[i]] = i;
// Calculate the initial number of rounds
int count = 1;
for (int i = 1; i < n; i++)
// Increase the count if there is an inversion i.e.
// if the position of i is greater than the position
// of i+1
count += (position[i] > position[i + 1]);
// Declare a set to store the pairs of values that will
// be updated
set<pair<int, int> > updatedPairs;
for (int i = 0; i < m; i++) {
// Declare two integers l and r to store the
// positions to be swapped
int l = swaps[i][0], r = swaps[i][1];
// Insert the pairs of values that will be updated
// into the set
if (values[l] + 1 <= n)
updatedPairs.insert(
{ values[l], values[l] + 1 });
if (values[l] - 1 >= 1)
updatedPairs.insert(
{ values[l] - 1, values[l] });
if (values[r] + 1 <= n)
updatedPairs.insert(
{ values[r], values[r] + 1 });
if (values[r] - 1 >= 1)
updatedPairs.insert(
{ values[r] - 1, values[r] });
// Update the count before the swap
for (auto swapped : updatedPairs)
// Subtract from the count, the inversions
// formed by our current set as there may be
// some elements that don’t form an inversion
// after the swap and if they form they'll be
// counted.
count -= position[swapped.first]
> position[swapped.second];
// Perform the swap
swap(values[l], values[r]);
// Update the position of the value at position l
position[values[l]] = l;
// Update the position of the value at position r
position[values[r]] = r;
// Update the count after the swap
for (auto swapped : updatedPairs)
// Count and add the inversions by adjacent
// elements to our existing count.
count += position[swapped.first]
> position[swapped.second];
// Add the count to the result vector.
res.push_back(count);
// Clear the set for the next operation
updatedPairs.clear();
}
// Return result
return res;
}
// Driver Code
int main()
{
int n = 5, m = 3;
vector<int> values = { 4, 2, 1, 5, 3 };
vector<vector<int> > swaps
= { { 2, 3 }, { 1, 5 }, { 2, 3 } };
vector<int> res
= collectingnumbersII(n, m, values, swaps);
for (auto i : res)
cout << i << "\n";
return 0;
}
Java
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Main {
public static List<Integer> GFG(int n, int m, int[] values, int[][] swaps) {
// Make the array 1-indexed
List<Integer> res = new ArrayList<>();
int[] position = new int[n + 1];
// Store the positions of the values
for (int i = 1; i <= n; i++) {
position[values[i]] = i;
}
// Calculate the initial number of rounds
int count = 1;
for (int i = 1; i < n; i++) {
// Increase the count if there is an inversion i.e.
// if the position of i is greater than the position
// of i+1
count += position[i] > position[i + 1] ? 1 : 0;
}
// Declare a set to store the pairs of the values that will
// be updated
Set<List<Integer>> updatedPairs = new HashSet<>();
for (int i = 0; i < m; i++) {
int l = swaps[i][0];
int r = swaps[i][1];
// Insert the pairs of the values that will be updated
// into the set
if (values[l] + 1 <= n) {
updatedPairs.add(List.of(values[l], values[l] + 1));
}
if (values[l] - 1 >= 1) {
updatedPairs.add(List.of(values[l] - 1, values[l]));
}
if (values[r] + 1 <= n) {
updatedPairs.add(List.of(values[r], values[r] + 1));
}
if (values[r] - 1 >= 1) {
updatedPairs.add(List.of(values[r] - 1, values[r]));
}
// Update the count before the swap
for (List<Integer> swapped : updatedPairs) {
count -= position[swapped.get(0)] > position[swapped.get(1)] ? 1 : 0;
}
// Perform the swap
int temp = values[l];
values[l] = values[r];
values[r] = temp;
// Update the position of value at position l
position[values[l]] = l;
position[values[r]] = r;
// Update the count after the swap
for (List<Integer> swapped : updatedPairs) {
count += position[swapped.get(0)] > position[swapped.get(1)] ? 1 : 0;
}
// Add the count to result list
res.add(count);
updatedPairs.clear();
}
// Return result
return res;
}
// Driver Code
public static void main(String[] args) {
int n = 5, m = 3;
int[] values = {0, 4, 2, 1, 5, 3}; // Make the array 1-indexed
int[][] swaps = {{2, 3}, {1, 5}, {2, 3}};
List<Integer> res = GFG(n, m, values, swaps);
for (int i : res) {
System.out.println(i);
}
}
}
Python
def GFG(n, m, values, swaps):
# Make the array 1-indexed
values.insert(0, 0)
res = []
position = [0] * (n + 1)
# Store the positions of the values
for i in range(1, n + 1):
position[values[i]] = i
# Calculate the initial number of rounds
count = 1
for i in range(1, n):
# Increase the count if there is an inversion i.e.
# if the position of i is greater than the position
# of i+1
count += position[i] > position[i + 1]
# Declare a set to the store the pairs of the values that will
# be updated
updated_pairs = set()
for i in range(m):
l, r = swaps[i]
# Insert the pairs of the values that will be updated
# into the set
if values[l] + 1 <= n:
updated_pairs.add((values[l], values[l] + 1))
if values[l] - 1 >= 1:
updated_pairs.add((values[l] - 1, values[l]))
if values[r] + 1 <= n:
updated_pairs.add((values[r], values[r] + 1))
if values[r] - 1 >= 1:
updated_pairs.add((values[r] - 1, values[r]))
# Update the count before the swap
for swapped in updated_pairs:
count -= position[swapped[0]] > position[swapped[1]]
# Perform the swap
values[l], values[r] = values[r], values[l]
# Update the position of value at position l
position[values[l]] = l
position[values[r]] = r
# Update the count after the swap
for swapped in updated_pairs:
count += position[swapped[0]] > position[swapped[1]]
# Add the count to result list.
res.append(count)
updated_pairs.clear()
# Return result
return res
# Driver Code
if __name__ == "__main__":
n, m = 5, 3
values = [4, 2, 1, 5, 3]
swaps = [[2, 3], [1, 5], [2, 3]]
res = GFG(n, m, values, swaps)
for i in res:
print(i)
JavaScript
function GFG(n, m, values, swaps) {
// Make the array 1-indexed
values.unshift(0);
let res = [];
let position = new Array(n + 1).fill(0);
// Store the positions of the values
for (let i = 1; i <= n; i++) {
position[values[i]] = i;
}
// Calculate the initial number of rounds
let count = 1;
for (let i = 1; i < n; i++) {
// Increase the count if there is an inversion i.e.
// if the position of i is greater than the position
// of i+1
count += position[i] > position[i + 1];
}
// Declare a set to store the pairs of the values that will
// be updated
let updatedPairs = new Set();
for (let i = 0; i < m; i++) {
let [l, r] = swaps[i];
// Insert the pairs of the values that will be updated
// into the set
if (values[l] + 1 <= n) {
updatedPairs.add([values[l], values[l] + 1]);
}
if (values[l] - 1 >= 1) {
updatedPairs.add([values[l] - 1, values[l]]);
}
if (values[r] + 1 <= n) {
updatedPairs.add([values[r], values[r] + 1]);
}
if (values[r] - 1 >= 1) {
updatedPairs.add([values[r] - 1, values[r]]);
}
// Update the count before the swap
for (let swapped of updatedPairs) {
count -= position[swapped[0]] > position[swapped[1]];
}
// Perform the swap
[values[l], values[r]] = [values[r], values[l]];
// Update the position of value at position l
position[values[l]] = l;
position[values[r]] = r;
// Update the count after the swap
for (let swapped of updatedPairs) {
count += position[swapped[0]] > position[swapped[1]];
}
// Add the count to result list
res.push(count);
updatedPairs.clear();
}
// Return result
return res;
}
// Driver Code
let n = 5, m = 3;
let values = [4, 2, 1, 5, 3];
let swaps = [[2, 3], [1, 5], [2, 3]];
let res = GFG(n, m, values, swaps);
for (let i of res) {
console.log(i);
}
Time Complexity: O(n), where n is the size of the array.
Auxiliary Space: O(n), where n is the size of the array.
Similar Reads
CSES Solutions - Collecting Numbers
You are given an array arr[] that contains each number between 1 ... N exactly once. Your task is to collect the numbers from 1 to N in increasing order. On each round, you go through the array from left to right and collect as many numbers as possible. What will be the total number of rounds? Examp
6 min read
CSES Solutions - Counting Numbers
Given two integers a and b. Your task is to count the number of integers between a and b where no two adjacent digits are the same. Examples: Input: a=11, b=13Output: 2Explanation: The two numbers are 12 and 13. Input: a=123, b=321Output: 171 Approach:The idea is to use digit DP to solve this proble
9 min read
CSES Solutions - Coin Piles
You are given Q queries. In each query, you have two coin piles containing A and B coins. On each move, you can either remove one coin from the left pile and two coins from the right pile, or two coins from the left pile and one coin from the right pile. Your task is to efficiently find out if you c
7 min read
CSES Solutions - Missing Coin Sum
You are given an array of positive integers coins[] of size n, representing n coins of different denominations. The task is to find the smallest sum that can not be created using a subset of the coins[]. Note: Each coin can only be used once. Examples: Input: coins[] = [2, 9, 1, 2, 7]Output: 6Explan
5 min read
CSES Solutions - Minimizing Coins
Consider a money system consisting of N coins. Each coin has a positive integer value. Your task is to produce a sum of money X using the available coins in such a way that the number of coins is minimal. Examples: Input: N = 3, X = 11, coins[] = {1, 5, 7}Output: 3Explanation: We need minimum 3 coin
7 min read
CSES Solutions - Coin Combinations II
Consider a money system consisting of N coins. Each coin has a positive integer value. Your task is to calculate the number of distinct ordered ways you can produce a money sum X using the available coins. Examples: Input: N = 3, X = 9, coins[] = {2, 3, 5}Output: 3Explanation: There are three ways t
8 min read
CSES Solutions - Dice Combinations
Your task is to count the number of ways to construct sum N by throwing a dice one or more times. Each throw produces an outcome between 1 and 6. Examples: Input: N = 3Output: 4Explanation: There are 4 ways to make sum = 3. Using 1 die {3}, sum = 3.Using 2 dice {1, 2}, sum = 1 + 2 = 3.Using 2 dice {
8 min read
CSES Solutions - Coin Combinations I
Consider a money system consisting of N coins. Each coin has a positive integer value. Your task is to calculate the number of distinct ways you can produce a money sum X using the available coins. Examples: Input: N = 3, X = 9, coins[] = {2, 3, 5}Output: 8Explanation: There are 8 number of ways to
8 min read
CSES Solutions - Two Sets
Given N numbers 1,2,3,... N. Your task is to divide the numbers into two sets of equal sum. Print "YES", if the division is possible, and "NO" otherwise. If the division is possible, print how to create the sets. First, print the number of elements in the first set followed by the elements themselve
10 min read
Find the number of solutions to the given equation
Given three integers A, B and C, the task is to find the count of values of X such that the following condition is satisfied, X = B * Sm(X)A + C where Sm(X) denotes the sum of digits of X and 1 < X < 109.Examples: Input: A = 3, B = 2, C = 8 Output: 3 For X = 10, 2 * (1)3 + 8 = 10 For X = 2008,
6 min read