How do I deal with large arrays in c++/STL? - c++

I am trying to solve this problem arraysub on spoj. I have coded it using a sliding window concept and I am using a max-heap to store the elements of the current window. The problem constraints are of the order 10^5 and I am getting SIGABRT error for my submission. I've read on wiki that this error results if there's a memory leak or problem initialising large arrays. How do I deal with this? long long, long long int, long long unsigned int, doesn't seem to work. Please help. Below is my code:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
typedef pair<long, long> Pair;
long *a = new long[1000001], *output = new long[1000001];
long n, k;
void slidingWindowMax()
{
priority_queue<Pair> Q;
for(int i=0;i<k; i++)
Q.push(Pair(a[i], i));
for(int i=k; i<n; i++)
{
Pair p = Q.top();
output[i-k] = p.first;
while(p.second <= i-k)
{
Q.pop();
p = Q.top();
}
Q.push(Pair(a[i], i));
}
output[n-k] = Q.top().first;
for(int i=0;i<(n-k+1);i++)
{
cout << output[i] << " ";
}
}
int main()
{
cin >> n;
for(int i=0;i<n;i++)
cin >> a[i];
cin >> k;
slidingWindowMax();
return 0;
}

Related

How to solve runtime error in finding the largest number among n numbers

As I'm new to c++ I get runtime error for first example(I mean I tested my program with 5 examples it actually happens automatically by a site for testing) of my program I know that's because of exceeding time for running it but I dunno how to fix this.
My program get n numbers from user and finds the largest one and prints it.
#include<iostream>
#include<curses.h>
using namespace std;
int main()
{
int n;
cin >> n;
int *p = new int(n);
for(int i = 1; i<=n; i++){
cin >> *(p+i);
}
int largest = *p;
for(int i = 1; i<=n; i++){
if(largest < *(p+i))
largest = *(p+i);
}
cout << largest;
return(0);
}
int *p=new int(n);
The line above allocates just a single int, and sets the value to n. It does not allocate an array of n integers.
That line should be:
int *p=new int[n];
And then delete [] p; to deallocate the memory.
But better yet:
#include <vector>
//...
std::vector<int> p(n);
is the preferred way to utilize dynamic arrays in C++.
Then the input loop would simply be:
for(int i=0;i<n; i++)
{
cin >> p[i];
}
That same input loop could have been used if you had used the pointer version.
Then you have this error:
for(int i=1;i<=n;i++)
Arrays (and vectors) are indexed starting from 0 with the upper index at n-1, where n is the total number of elements. That loop has an off-by-one error, where it exceeds the upper index on the last loop.
Basically any loop that uses <= as the limiting condition is suspect. That line should be:
for(int i=0; i<n; i++)
(Note that I changed the code above to fix this error).
However ultimately, that entire loop to figure out the largest can be accomplished with a single line of code using the std::max_element function:
#include <algorithm>
//...
int largest = *std::max_element(p, p + n);
and if using std::vector:
#include <algorithm>
//...
int largest = *std::max_element(p.begin(), p.begin() + n);
I've commented on suggested changes in this slightly modified version:
#include <iostream>
int main()
{
unsigned n; // don't allow a negative amount of numbers
if(std::cin >> n) { // check that "cin >> n" succeeds
int* p=new int[n]; // allocate an array of n ints instead of one int with value n
for(int i=0; i < n; ++i) { // corrected bounds [0,n)
if(not (std::cin >> p[i])) return 1; // check that "cin >> ..." succeeds
}
int largest = p[0];
for(int i=1; i < n; ++i) { // corrected bounds again, [1,n)
if(largest < p[i])
largest = p[i];
}
delete[] p; // free the memory when done
std::cout << largest << '\n';
}
}
Note that using *(p + i) does the same as using p[i]. The latter is often preferred.
This would work if all cin >> ... works, but shows some of the hazards when using raw pointers. If extracting the n ints failes, the program will return 1 and leak the memory allocated with new int[n].
A rewrite using a smart pointer (std::unique_ptr<int[]>) that automatically deallocates the memory when it goes out of scope:
#include <iostream>
#include <memory> // std::unique_ptr
int main()
{
unsigned n;
if(std::cin >> n) {
std::unique_ptr<int[]> p(new int[n]);
for(int i=0; i < n; ++i) { // corrected bounds [0,n)
if(not (std::cin >> p[i])) return 1; // will not leak "p"
}
int largest = p[0];
for(int i=1; i < n; ++i) {
if(largest < p[i])
largest = p[i];
}
std::cout << largest << '\n';
} // p is automatically delete[]ed here
}
However, it's often convenient to store an array and its size together and to do this, you could use a std::vector<int> instead. It comes with a lot of convenient member functions, like, size() - and also begin() and end() which lets you use it in range-based for loops.
#include <iostream>
#include <vector> // std::vector
int main()
{
unsigned n;
if(std::cin >> n) {
std::vector<int> p(n); // a vector of n ints
// a range-based for loop, "elem" becomes a refrence to each element in "p":
for(int& elem : p) {
if(not (std::cin >> elem)) return 1;
}
int largest = p[0];
for(int i = 1; i < p.size(); ++i) { // using the size() member function
if(largest < p[i])
largest = p[i];
}
std::cout << largest << '\n';
}
}
That said, you don't need to store any number in an array to figure out what the largest number is. Instead, just compare the input with the currently largest number.
#include <iostream>
#include <limits> // std::numeric_limits
int main()
{
unsigned n;
if(std::cin >> n) {
// initialize with the smallest possible int:
int largest = std::numeric_limits<int>::min();
while(n--) {
int tmp;
if(not (std::cin >> tmp)) return 1;
if(largest < tmp)
largest = tmp;
}
std::cout << largest << '\n';
}
}

I'm having an issue with not converting const__gnu_cxx::__normal_iterator<long long int* , std:: vector<long long int>

I'm trying to solve a question from a Div 3 competition. I'm having troubles with line 25 and 26, it's saying
error: cannot convert ' const__gnu_cxx::__normal_iterator<long long int*, std::vector<long long int>
I'm not too sure what's wrong. The goal for this line is to store the minimum of vector a and b into a long long integer amin and bmin.
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define endl "\n"
void solve(){
ll input;
ll total;
int amount; cin >> amount;
vector<ll> a, b;
for(int i = 0; i < amount; i++){
cin >> input;
a.push_back(input);
}
for (int i = 0; i < amount; i++){
cin >> input;
b.push_back(input);
}
ll amin, bmin;
amin = min(a.begin(), a.end());
bmin = min(b.begin(), b.end());
ll adif, bdif, totaldif;
for(int i = 0; i < amount; i++){
adif = a[i] - amin;
bdif = b[i] - bmin;
totaldif = abs(adif - bdif);
total += (adif - totaldif) + (bdif - totaldif) + totaldif;
}
cout << total << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t; cin >> t;
while(t--){
solve();
}
}
std::min returns the minimum of 2 elements, not the minimum element of a range. Assuming you don't want the minimum of 2 iterators, but the minimum element of a range, you need std::min_element and you need to dereference the result, like this:
amin = * min_element(a.begin(), a.end());
// ^
And you need to do the same thing for bmin.
Also, please avoid using namespace std; and all the #defines for the types, it just makes the code more confusing to read.

c++ runtime error when using vectors push back and iterator

Hi I'm trying to solve a algorithm problem and when I submit my code on an online judge I keep on getting a runtime error. I have no idea why it is happening.
Here is the problem that I'm trying to solve.
The code is as follows. It works fine for the sample input and outputs in visual studio. I haven't yet met inputs and outputs that does not work well or actually meet the runtime error. Only the online judge is giving the runtime error so I can't figure out why.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
int m;
int c1;
int c2;
cin >> n >> m >> c1 >> c2;
vector<int> p = {};
vector<int> q = {};
for (int i = 0; i < n; ++i)
{
int temp;
cin >> temp;
p.push_back(temp);
}
for (int i = 0; i < m; ++i)
{
int temp;
cin >> temp;
q.push_back(temp);
}
vector<int> distance = {};
for (int i = 0; i < p.size(); ++i)
{
for (int j = 0; j < q.size(); ++j)
{
distance.push_back(abs(p[i] - q[j]) + abs(c1 - c2));
}
}
sort(distance.begin(), distance.end());
int min = distance[0];
int count = 0;;
for (int i = 0; i < static_cast<int>(distance.size()); ++i)
{
if (distance[0] == distance[i])
count++;
else
break;
}
cout << min << " " << count << endl;
return 0;
}
If n and m are both the maximum allowed value of 500,000 then distance will have 500,000 * 500,000 elements which will use 1TB of memory. Due to vector growing as you push_back you could actually need around 2TB of memory in total. The online judge presumably doesn't allow you to use this much memory.
If you rethink your algorithm to not store the values of distance it will probably work.
You should lways use reserve on std::vector if you know the size in advance as it should cause the vector to allocate exactly the right amount of memory and avoid copying to new blocks of memory as the vector grows.

Store Very Large Arrays in C++?

So I am working on a problem at HackerEarth which requires me to store an integer array of size 10^9.
I am trying to store the array using vector but I get runtime error SIGABRT when I try to Submit my Solution.
Here is my code:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
unsigned int h, c, q;
cin >> h >> c >> q;
vector<unsigned int> minht(h + 1);
for (unsigned int i = 0; i <= h; i++)
minht[i] = 0;
unsigned int hc, st, et;
for (unsigned int i = 1; i <= c; i++)
{
cin >> hc >> st >> et;
for (unsigned int j = 1; j <= h; j++)
{
if (j >= st && j <= et)
{
if (hc > minht[j])
minht[j] = hc;
}
}
}
unsigned int hq, tq;
for (unsigned int i = 1; i <= q; i++)
{
cin >> hq >> tq;
if (hq > minht[tq])
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}
The code works fine when value of h is not very large(10^9) but I get SIGABRT when value of h is very large.
Any Suggestions?
EDIT:
So I tried rewriting my entire code and my new code looks like this:
#include<iostream>
#include<vector>
using namespace std;
int main()
{
unsigned int h,c,q,mh=0;
cin>>h>>c>>q;
vector<unsigned int> hc(c+1);
vector<unsigned int> st(c+1);
vector<unsigned int> et(c+1);
for(unsigned int i=1;i<=c;i++)
{
cin>>hc[i]>>st[i]>>et[i];
if(mh<hc[i])mh=hc[i];
}
unsigned int ht,ti;
for(unsigned int i=1;i<=q;i++)
{
int flag=0;int ct=0;
cin>>ht>>ti;
if(ht<=mh)
{
for(unsigned int j=1;j<=c;j++)
{
if(ti>=st[j] && ti<=et[j])
{
if(ht<=hc[j])
{
ct=1;break;
}
}
}
}
if(ct==0)cout<<"YES\n";
else cout<<"NO\n";
}
}
and the solution was now accepted.
What I did was redesign the algorithm so that instead of having to store 1 VERY LARGE array of 4 GB, I had to store 3 LARGE arrays, each of maximum 40 MB.
So the problem is now solved but I but I still don't think that problem was related to memory issues.
Because when I tried to create a int vector of size 10E8, just to test out the online compiler, I got a specific Memory Limit Exceeded Error. But when I changed the size to 10E9 I got SIGABRT again. So although the memory issue is there, SIGABRT is being caused by declaring an array of 10E9 size.
Any idea what could be causing this??
Also, I first created the program on my own compiler and then submitted it online. I can't debug the program on my setup since the program requires me to enter 10E7 data values before I encounter the error, so I thought that it would be easier to do it on HackerEarth.

Boolean array getting unexpected default values

I wrote the following C++ program to implement breadth first search to solve this problem of finding shortest path for all the nodes from the source.
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;
int main()
{
int test;
cin >> test;
while(test--)
{
int m,n,source;
cin >> n >> m;
bool visited[n+1];
int dist[1001];
queue<int> q;
memset(dist, -1, sizeof(dist));
vector<int> adj[1001];
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
cin >> source;
dist[source] = 0;
visited[source] = true;
q.push(source);
while(q.size())
{
int v = q.front();
q.pop();
for(int i : adj[v])
{
if(!visited[i])
{
q.push(i);
dist[i] = dist[v] + 6;
visited[i] = true;
}
}
}
for(int i = 1; i <= n; i++)
{
if(i != source)
{
cout << dist[i] << " ";
}
}
cout << "\n";
}
}
It works well if the value of test is 1, but when the value is 2 or more, some values of the boolean array "visited" become 1 in the second and later iterations. I do not understand why and how it happens as I declare the boolean array in every iteration and the default value for its elements is 0. Can somebody please explain this.
I declare the boolean array in every iteration and the default value for its elements is 0.
No, it's not 0. There are no default values for C++ simple types. My bet is you propably get some random values, as your array isn't initialised automatically.
You aren't initialising the array, and local arrays are not zero initialised, so explicit initialisation is needed.