Difficulty understanding code to count the number of inversions using BIT - c++

Here is the code:
#include<iostream>
using namespace std;
const int MX = 100;
int n,a[MX*2],bit[MX];
void add(int x, int y){
for(;x<=n; x+=-x&x) bit[x]+=y;
}
int query(int x){
int s= 0;
for(;x>0; x-=-x&x) s+=bit[x];
return s;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int ans = 0;
cin >> n; n*=2;
for(int i = 0; i<n; i++){
cin >> a[i];
}
for(int i = n-1; ~i; i--){
ans+=query(a[i]-1);
add(a[i],1);
}
cout << ans;
}
I dont understand how the query and add contribute to finding the number of inversions in an array. If someone can help explain this to me that would be great. Thanks.

Firstly, I hope you understand how add and query work in BIT. If not, think of BIT like a blackbox which stores prefix sums for count of elements 1, 2, ..., n in array A. For example, A[3] = count(1) + count(2) + count(3). add(x, y) increments count(x) by y and query(x) returns the sum count(1) + count(2) + ... + count(x) i.e., the prefix sum till element x.
Elements at index i and j form an inversion if i < j and arr[i] > arr[j]. But the above code reads it the other way; j > i and arr[j] < arr[i] (this save an extra call to query).
Now suppose the array is {3, 4, 1, 5, 2} and {2, 5, 1} have already been inserted in the BIT. Then query(1) = 1, query(2) = 2, query(3) = 2, query(4) = 2 and query(5) = 3 (remember to think of BIT as a blackbox that stores prefix sums). Notice when index i is pointing at element 4, all the elements that have already been inserted having indices j1, j2, ..., jk are all > i so now we only need to count the number of elements < 4 which is the prefix sum till 3 which we get by calling query(3).

Related

How does a 2D array within another array work?

I am looking at my homework for c++ and having some trouble understanding a part of the code. The code is creating a 2d array and wants to know how many times the elements from 1-9 are repeated.
#include <iostream>
using namespace std;
const int r = 3;
const int c = 4;
void frequency (int a[r][c]);
int main() {
int elems [r][c] = {{1, 1, 3, 4}, {2, 3, 4, 5}, {6, 9, 9, 9}};
frequency(elems);
return 0;
}
void frequency(int a[r][c]){
int arr[10] = {};
for(int i = 0; i < r; i++){
for(int j = 0; j < c; j++){
arr[a[i][j]]++;
}
}
for(int i = 1; i < 10; i++){
cout << i << " is repeated " << arr[i] << " times." << endl;
}
}
I don't understand how the line arr[a[i][j]]++; works -- how does it act as a counter for elements that are repeated?
I don't understand how the line arr[a[i][j]]++; works -- how does it act as a counter for elements that are repeated?
int arr[10] = {}; is creating an int-array with 10 elements (indexed 0-9) all initialized to 0.
arr[a[i][j]]++; is (post-)incrementing an element of arr.
The element at which index? The one at index a[i][j].
You loop through every row in a (i.e. in elems) using i and through every column within that row using j; in essence looping through every element in the order they are spelled in the source code. You are using the numbers in array a to index into the array arr: The first two elements of elems are 1, thus you increment arr[1]. The third number in elems is 3, thus you increment arr[3], ...

Moving array elements over one position

I have a homework assignment where we're supposed to create a list of integers, and allow the user to INSERT an integer at a given position in the list. The list should essentially move all integers over one position in the array, then insert the integer that the user input at the index they chose.
So let's say I have an array of {1, 2, 3, 4, 5} and I want to put 9 in index 1, the array should then be {1, 9, 2, 3, 4, 5}.
I thought I figured out the solution with this function:
void *INSERT(int count, int userNum, int index, int array[]){ //Accepts count of array, users number, users index, and array
int tempIndex = index;
index--;
for(int counter = 0; counter < count; counter++)
{
array[tempIndex] = array[tempIndex-1];
tempIndex++;
}
array[index] = userNum;
}
Here is what I have in the main function:
int index = 0; //Hold users index selection
int userNum = 0; //Hold users number
int n = 10;
int a[n] = {1, 2, 3, 4, 5};
int *ptr = a;
cout << "Enter a number to insert: ";
cin >> userNum;
cout << "Enter an index: ";
cin >> index;
INSERT(n, userNum, index, ptr);//call insert function (Accepts count of array, users number, users index, and array)
int listNum = 1;
for(int i = 0; i < n; i++) {
cout << listNum << ". " << a[i] << "\n";
listNum++;
}
However, this is the output after printing the array:
1. 1
2. 9
3. 2
4. 2
5. 2
6. 2
7. 2
8. 2
9. 2
10. 2
I'm not sure where I'm going wrong here that could be causing this output. If I remove the -1 from the INSERT functions for loop like this(commented it out to make it more clear on what's being changed):
void *INSERT(int c, int n, int i, int a[]){ //Accepts count of array, users number, users index, and array
int x = i;
i--;
for(int r = 0; r < c; r++)
{
a[x] = a[x/*-1*/];
x++;
}
a[i] = n;
}
I get the following output with the above code, which is what I'd expect but not what I need. I can post the entire code if needed as well, but I think this explains where the problem is. Thanks in advance for the help
1. 1
2. 9
3. 3
4. 4
5. 5
6. 0
7. 0
8. 0
9. 0
10. 0
Based on your code, just change your insert function to this -
Here we first shift the values to next index in the array and then perform insertion of respective element
void *INSERT(int c, int n, int i, int a[]){ //Accepts count of array, users number, users index, and array
for(int r = c-1; r >= i; r--)
{
a[r+1] = a[r];
}
a[i] = n;
}
This answer may be somewhat controversial because instead of directly solving your assignment for you I'm just telling you how to debug it so you can solve it yourself.
So fixed your code for you:
//Accepts count of array, users number, users index, and array
void *INSERT(
int array_size,
int number_to_insert,
int insert_at,
int numbers[]){
int moving_index = insert_at;
insert_at--; // Why are you doing this?
for(int r = 0; r < array_size; r++)
{
// moving_index was initialized as insert_at
// What happens when insert_at is 0?
// What happens when moving_index >= array_size?
// Who knows...
numbers[moving_index] = numbers[moving_index-1];
// You're incrementing moving_index.
moving_index++;
// What would numbers[moving_index-1] be now?
}
numbers[insert_at] = number_to_insert;
}
Once you answer my questions, I'm sure you'll be able to figure it out.

Sort 2 unsorted arrays in a single sorted array in c++

Sort 2 unsorted arrays in one sorted array for best time complexity of O(n+m) in c++ language. How can we modify this code to make it for O(m+n) time complexity? The 2 array sizes should be different. Here the time complexity is O((m+n)log(m+n)). How to make it O(m+n) complexity?
#include <bits/stdc++.h>
using namespace std;
// Function to merge array in sorted order
void sortedMerge(int a[], int b[], int res[],
int n, int m)
{
// Concatenate two arrays
int i = 0, j = 0, k = 0;
while (i < n) {
res[k] = a[i];
i += 1;
k += 1;
}
while (j < m) {
res[k] = b[j];
j += 1;
k += 1;
}
// sorting the res array
sort(res, res + n + m);
}
// Driver code
int main()
{
int a[] = { 10, 5, 15 };
int b[] = { 20, 3, 2, 12 };
int n = sizeof(a) / sizeof(a[0]);
int m = sizeof(b) / sizeof(b[0]);
// Final merge list
int res[n + m];
sortedMerge(a, b, res, n, m);
cout << "Sorted merged list :";
for (int i = 0; i < n + m; i++)
cout << " " << res[i];
cout << "n";
return 0;
}
Looking at your problem I think you forgot one little detail: is your arrays always guaranteed to contain postive integers?? If so, use a third array and store the two arrays values inside it. Then use radix sort to sort it, or if you know the range, use counting sort. I attached the link instead of explaining since explaining such complex sorting algorithms here would take way to long.
Counting sort: https://www.geeksforgeeks.org/counting-sort/#:~:text=Counting%20Sort,object%20in%20the%20output%20sequence.
Radix Sort: https://www.geeksforgeeks.org/radix-sort/

C++ array operations

I want from the program to add 3 to elements which are greater than 3 and print them. It takes so much time that I couldn't see the result. Also, when I change n to 8 in loops directly, it gives a result; however, it's not related with what I want. How can I correct this code and improve that?
#include <iostream>
using namespace std;
int main()
{
int a[8] = {-5, 7, 1, 0, 3, 0, 5, -10};
int b[8];
int n= sizeof(a);
for( int i=1; i<=n; i++) {
if (a[i]>3) {
b[i] = a[i] + 3;
}
else {
b[i]= a[i];
}
}
for (int i = 1; i <= n; i++)
cout << b[i];
return 0;
}
The sizeof() function (int n = sizeof(a)) gives 32 because array 'a' contains 8 elements & each element is of 'int' type whose size is 4 byte in memory thats why it returns 32 in 'n' variable.so you must divide the value of 'n' with the size of integer.
Secondly the index of array starts with the zero '0' to one less than the length of array not with the 1 to length of array .
Try the below code ! I am also attach the output of the code .
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int a[8] = { -5, 7, 1, 0, 3, 0, 5, -10 };
int b[8];
int n = sizeof(a)/sizeof(int);
for (int i = 0; i < n; i++) {
if (a[i]>3) {
b[i] = a[i] + 3;
}
else {
b[i] = a[i];
}
}
for (int i = 0; i < n; i++)
cout << b[i]<<endl;
return 0;
}
The statement in your program int n=size(a) returns the total bytes occupied in memory for a. i.e int occupies 4 bytes and a is an array contains 8 elements so 8X4 = 32 .but while accessing the array elements using loop you are specifying i<=n meains i<=32 but there is only 8 elements but you are trying to access 32 elements which indicates that you are trying to access the elements more than 8.
exeutes the following code
#include <iostream>
using namespace std;
int main()
{
int a[8] = {-5, 7, 1, 0, 3, 0, 5, -10};
int b[8];
int n=sizeof(a);
cout<<"\n Value of n is : "<<n;
return 0;
}
Output
Value of n is : 32
if you specify the exact number of array size your program will work properly.
#include <iostream>
using namespace std;
int main()
{
int a[8] = {-5, 7, 1, 0, 6, 0, 8, -10};
int b[8];
for( int i=1; i<8; i++)
{
if (a[i]>3)
{
b[i] = a[i] + 3;
}
else
{
b[i]= a[i];
}
}
cout<<"\n Values in a array";
cout<<"\n -----------------\n";
for (int i = 1; i <8; i++)
cout << "\t"<<a[i];
cout<<"\n Values in b array";
cout<<"\n -----------------\n";
for (int i = 1; i <8; i++)
cout << "\t"<<b[i];
return 0;
}
OUTPUT
Values in a array
-----------------
7 1 0 6 0 8 -10
Values in b array
---------------
10 1 0 9 0 11 -10
I hope that you understand the concept.Thank you
Your int n = sizeof(a); doesn't works as you intend.
I think you want to get the size of array (i.e. 8).
But you gets the size in bytes of elements (e.g. 32, integer size or could be different depending of your system's architecture).
Change to int n = 8, will solve your problem.
Also note that for( int i=1; i<=n; i++) will get an "out of array" element.
Sizeof function gives the value of the total bits of memory the variable occupy
Here in array it stores 8 integer value that has 2bit size for each thus it returns 32

Sorting an array to another array C++

My program have to sort an array in another array.
When I run the program it prints 1 2 3 -858993460 5 -858993460 7.
I can not understand where the mistake is in the code.
#include <iostream>
using namespace std;
int main()
{
const int N = 7;
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int max = arr[0];
for (int i = 1; i < N; i++)
{
if (max < arr[i])
max = arr[i];
}
int sort_arr[N];
for (int j = 0; j < N; j++)
{
sort_arr[arr[j] - 1] = arr[j];
}
for (int i = 0; i < N; i++)
{
cout << sort_arr[i] << " ";
}
return 0;
}
Okay lets face the problems in your code.
The "weird" numbers you see there, came from the uninitialzied array sort_arr. What do I mean by uninitialized? Well sort_arr is a little chunck somewhere in your memory. Since a program usually does not clear its memory and rather claims the memory it used as free, the chunk of sort_arr may contain bits and bytes set by another program. The numbers occure since these bytes are interpreted as an integer value. So the first thing to do would be to initialize the array before using it.
sort_arr[N] = { 0, 0, 0, 0, 0, 0, 0 };
Now why did these numbers occure? Well you're probably expecting your algorithm to set all values in sort_arr which would result in an sorted array, right? Well but your algorithm isn't working that well. See this line:
sort_arr[arr[j] - 1] = arr[j];
What happens when j is 1? arr[1] is then evaluated to 17 and 17 - 1 equals 16. So sort_arr[arr[1] - 1] is the same as sort_arr[16] which exceeds the bounds of your array.
If you want to program a sorting algorithm by your self than I would recommend to start with an simple bubble sort algorithm. Otherwise, if you only need to sort the array have a look at the algorithm header. It is fairly simple to use:
#include <iostream>
#include <algorithm>
#include <iterator> // << include this to use begin() and end()
using namespace std;
int main()
{
const int N = 7;
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int sort_arr[N] = { 0, 0, 0, 0, 0, 0, 0 };
copy(begin(arr), end(arr), begin(sort_arr));
sort(begin(sort_arr), end(sort_arr));
for (int i = 0; i < N; i++)
{
cout << sort_arr[i] << " ";
}
cout << endl;
}
By the way. You're looking for the biggest value in your array, right? After you have sorted the array sort_arr[N - 1] is the biggest value contained in your array.
If you want to sort a array into another array then one way is you make a copy of the array and then use the sort function in the standard library to sort the second array.
int arr[10];
int b[10];
for(int i=0;i<10;i++)
{
cin>>arr[i];
b[i]=arr[i];
}
sort(b,b+10);
// this sort function will sort the array elements in ascending order and if you want to change the order then just add a comparison function as third arguement to the sort function.
It seems that you think that sort_arr[arr[j] - 1] = arr[j] will sort arr into sort_arr. It won't.
Sorting is already written for you here: http://en.cppreference.com/w/cpp/algorithm/sort You can use that like this:
copy(cbegin(arr), cend(arr), begin(sort_arr));
sort(begin(sort_arr), end(sort_arr));
Live Example
My guess is this is an attempt to implement a type of counting sort. Note that variable length arrays aren't normally allowed in C++ or some versions of C. You could use _alloca() to allocate off the stack to get the equivalent of a variable length array: int * sort_arr = (int *)_alloca(max * sizeof(int)); .
#include <iostream>
using namespace std;
int main()
{
const int N = 7;
// assuming range of values is 1 to ...
int arr[N] = { 3, 17, 2, 9, 1, 5, 7 };
int max = arr[0];
for (int i = 1; i < N; i++)
{
if (max < arr[i])
max = arr[i];
}
int sort_arr[max];
for (int i = 0; i < max; i++)
{
sort_arr[i] = 0;
}
for (int j = 0; j < N; j++)
{
sort_arr[arr[j] - 1]++;
}
for (int i = 0; i < max; i++)
{
while(sort_arr[i])
{
cout << i+1 << " ";
sort_arr[i]--;
}
}
return 0;
}