Time Complexity of two codes - c++

What makes the first code faster than the second?
I tried those 2 codes one gave me a Time limit that exceeded 1000 ms and the other works on 140ms at a long test input of CodeForces test
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
int n, m, a, l, r, c(0), d(0);
scanf("%d%d", &n, &m);
while (n--)
{
scanf("%d", &a);
if (a == 1)
{
c += 1;
}
else
{
d += 1;
}
}
int up = min(c, d) * 2;
while (m--)
{
scanf("%d%d", &l, &r);
printf((r - l) % 2 == 1 && r - l < up ? "1\n" : "0\n");
}
return 0;
}
the slow one is:
#include <bits/stdc++.h>
int main()
{
int n, ones{}, _ones{}, l, r, q, temp;
std::cin >> n >> q;
while(n--)
{
std::cin >> temp;
if(temp == 1)
ones++;
else
_ones++;
}
int common = std::min(ones, _ones) * 2;
while(q--)
{
std::cin >> l >> r;
std::cout << ((r - l) % 2 == 1 && r - l < common ? "1\n" : "0\n");
}
}

I'm not sure if library imports/includes are counted, but doing the #include <bits/stdc++.h> usually takes a lot of time generally
Might be because of that, maybe include only the ones you need

Related

When submitting to Codeforeces output isn't the same as in the console

I'm trying to solve this problem: (https://codeforces.com/contest/1363/problem/A), and in my console when I give it the Input of the first example it outputs the right answer. but when submitting the code it says that my output was wrong and I dont know what's the problem.
this is my code:
#include <iostream>
#include <vector>
#include <math.h>
#define endl '\n'
using namespace std;
bool solve(int sum, int n, int x, int i, vector<int> v)
{
if(x == 0)
return sum % 2 != 0;
bool c1, c2;
c1 = solve(sum + v[i], n, x - 1, i + 1, v);
if(i == n - 1 - x)
c2 = solve(sum, n, x, i + 1, v);
return c1 || c2;
}
int main()
{
fast;
int t;
cin >> t;
while(t--)
{
int n, x;
cin >> n >> x;
vector<int> v(n);
for(int i = 0; i < n; i++)
cin >> v[i];
if(solve(0, n, x, 0, v))
cout << "Yes" << endl;
else
cout << "No" << endl;
}
}
The behaviour can be different, because your code has Undefined Behaviour - variable c2 in function solve can be used uninitialized.

How can I make this structure non-repetitive?

I need to make the following structure in a non-repetitive structure. Like the statement to run just one time. I tried to put "if" but that shows me the result 0.
I need to change this:
#include <iostream>
using namespace std;
int main() {
int n, i, s, x;
cin >> n;
s=0;
x=2;
for (i=1;i<=n;i++) {
s = s+x;
x = x+2;
}
cout << s;
return 0;
}
I tried this:
#include <iostream>
using namespace std;
int main() {
int n, i, s, x;
cin >> n;
s=0;
x=2;
if (i>=1 && i<=n) {
s = s+x;
x = x+2;
}
cout << s;
return 0;
}
The value to add (x) will be 2, 4, 6, 8, ....
This is an arithmetic progression and there is a formula to calculate the sum of specified number of elements.
Using the formula S_n = n/2 [2a_1 + (n-1)d] with a_1 = 2 and d = 2, the answer is:
#include <iostream>
using namespace std;
int main() {
int n, s;
cin >> n;
if (n >= 1) {
// s = n * (2 * 2 + (n - 1) * 2) / 2;
// s = n * (2 + (n - 1));
s = n * (n + 1);
} else {
s = 0;
}
cout << s;
return 0;
}

How do I optimise the code to return the number closest to a given integer, not present in the given list?

I solved this problem statement (Yeah Yeah, I know, I am putting the problem statement below).
Given are an integer X and an integer sequence of length N: p1, …, pN.
Among the integers not contained in the sequence p1, …, pN (not necessarily positive),
find the integer nearest to X, i.e. the integer whose absolute difference with X is the minimum.
If there are multiple such integers, report the smallest such integer
This is the code I used:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
int x = 0;
int n = 0;
std::cin >> x >> n;
std::vector<decltype(x)> vect(n);
bool vect_contains_x = false;
for (auto& elem : vect) {
std::cin >> elem;
if (elem == x) {
vect_contains_x = true;
}
}
int num = 0;
if (!vect_contains_x) {
num = x;
}
else {
std::sort(vect.begin(), vect.end());
while (1) {
static int i = 1;
if (std::find(vect.begin(), vect.end(), x - i) == vect.end()) {
num = x - i;
break;
}
else if (std::find(vect.begin(), vect.end(), x + i) == vect.end()) {
num = x + i;
break;
}
else {
i += 1;
}
}
}
std::cout << num << "\n";
return 0;
}
This code renders the result in 13-18ms.
I was able to get it down to 8-10ms by using the following optimised code:
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>
int main() {
int x = 0;
int n = 0;
std::cin >> x >> n;
std::vector<decltype(x)> vect(n);
bool vect_contains_x = false;
for (auto& elem : vect) {
std::cin >> elem;
if (elem == x) {
vect_contains_x = true;
}
}
int num = 0;
if (!vect_contains_x) {
num = x;
}
else {
std::sort(vect.begin(), vect.end());
auto isPresent = [=](auto num) {
for (const auto& elem : vect) {
if (num == elem) {
return true;
}
}
return false;
};
while (1) {
static int i = 1;
if (!isPresent(x - i)) {
num = x - i;
break;
}
else if (!isPresent(x + i)) {
num = x + i;
break;
}
else {
i += 1;
}
}
}
std::cout << num << "\n";
return 0;
}
However, the problem with both the codes (as they both use the same approach) is that,
If there is a large continuous stream of integers in the given list, something like:
1,2,3,4,5,6,7,8,9,10,...,1501
and the X given is
751
The code will need 750 iterations of the for loop, which is a lot. Can we use a better algorithm to find the closest integer?
EDIT:
Got it down to 6ms by using binary_search (Thanks #Sebastian), but still, the algorithm remains the same...
You can see this "cheating" algorithm. It's cheating because the _Find_next method is only in the GCC compiler. Also, with the help of printf and scanf, I accelerated input and output, due to which the program runs faster. I sent it for execution several times and received 4, 6 and 8 ms (6 ms most often):
#include <bitset>
#include <algorithm>
using namespace std;
int main()
{
const int MAX_VALUES = 101;
bitset<MAX_VALUES> bits;
bitset<MAX_VALUES> reversed;
bits.flip();
reversed.flip();
int x, n, t;
scanf("%d %d", &x, &n);
if (n == 0) {
printf("%d", x);
exit(0);
}
for (int i = 0; i < n; i++) {
scanf("%d", &t);
bits.reset(t);
reversed.reset(MAX_VALUES - 1 - t);
}
if (bits[x]) {
printf("%d", x);
exit(0);
}
int rV = bits._Find_next(x);
int lV = MAX_VALUES - 1 - reversed._Find_next(MAX_VALUES - 1 - x);
int d1 = abs(rV - x);
int d2 = abs(lV - x);
if (d1 < d2) {
printf("%d", rV);
} else if (d2 < d1) {
printf("%d", lV);
} else {
printf("%d", min(rV, lV));
}
return 0;
}
I am not saying that this "algorithm" is better than yours. But, as I understand it, you asked for some other solutions, this is one of the possible.
According to your link, the total number of integers is at most 100.
So 100 bits are enough to hold the flags, which numbers appear in the sequence. Those can be held in the processor registers.
The following code shows only the storage, afterwords you would have to chose suitable bit scan operations:
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <limits>
#include <bitset>
using namespace std;
int main() {
bitset<100> flags;
int x = 0;
int n = 0;
int min = std::numeric_limits<int>::max();
int num = 0;
std::cin >> x >> n;
for (int i = 0; i < n; i++) {
int elem;
std::cin >> elem;
flags.set(elem);
}
// then you can shift the result by x bits and do bit scan operations
// there are built-ins depending on the compiler and processor architecture or the portable De Bruijn with multiplications
}
// alternatively (to the shift) you can use two bitsets, and for one set all the elements (elem - x) or for the other (x - elem)

C++ Divide and conquer algorithm problems

I have just learnt about Divide and Conquer algorithm and I'm a little bit confused about it. The question is my homework, I have tried many ways to fix my code but it did not run.
#include <iostream>
using namespace std;
void inputArray(int* a, int& n)
{
cout << "Input n:";
cin >> n;
for (int i = 0; i < n; i++)
{
cout << "input a[" << i << "]= ";
cin >> a[i];
}
}
int sumeven(int* a, int l, int r)
{
if (l == r && a[l] % 2 == 0)
{
return a[l];
}
int mid = (l + r) / 2;
int s1 = sumeven(a, l, mid);
int s2 = sumeven(a, mid + 1, r);
return s1 + s2;
}
int main()
{
int n;
int a[20];
inputArray(a, n);
cout<<sumeven(a, 0,n-1);
return 0;
}
Try to test your programs without user input first:
#include <iostream>
using namespace std;
int sumeven(int* a, int l, int r)
{
if (r >= 6) return 0;
if (l > r ) return 0;
if (l >= r)
{
if (a[l] % 2 == 0)
{
return a[l];
}
else
{
return 0;
}
}
int mid = (l + r) / 2;
int s1 = sumeven(a, l, mid);
int s2 = sumeven(a, mid + 1, r);
return s1 + s2;
}
int main()
{
int n=6;
int a[6]={1,2,3,48,5,6};
cout<<sumeven(a,0,n-1);
return 0;
}

Segmented sieve of eratosthenes spoj Prime1 C++

I have been struggling with this problem http://www.spoj.com/problems/PRIME1/ and if anyone can help me finding the error in my code. I have used segmented sieve of eratosthenes and I have also looked through a lot of online resources but somehow I am getting a runtime error on spoj.
Thanks
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
#include <map>
#include <cstdlib>
#include <cassert>
#define fora(i,a,b) for(i = a; i < b; i++)
#define fin(f) freopen(f, "r", stdin)
#define fout(f) freopen(f, "w", stdout)
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
typedef vector<bool> vb;
const ll LIMIT = 1000000000;
void segmentedSieve(ll n, ll m, int segment_size) {
int i, j, s, p, range;
vb is_prime(range+1, true);
vb seg_primes(segment_size+1, true);
vi prime;
range = floor(sqrt((double)n));
fora (i, 2, range+1)
if (is_prime[i]) {
for (j = i*2; j <= range; j+=i)
is_prime[j] = false;
}
fora (i, 2, range+1)
if (is_prime[i] == 1)
prime.push_back(i);
fora (i, 0, prime.size()) {
p = prime[i];
s = m/p;
s *= p;
for (j = s; j <= n; j+=p) {
if (j < m) continue;
seg_primes[j-m] = false;
}
}
fora (i, 0, prime.size())
if (prime[i] >= m && prime[i] <= n) {
cout << prime[i] << endl;
}
fora (i, 0, n-m+1)
if (seg_primes[i] && (i+m) != 1) {
cout << i+m << endl;
}
}
int main()
{
int segment_size = 100000;
// fin("input.in");
int t;
cin >> t;
while (t--) {
ll a, b;
cin >> a >> b;
if (a > b)
segmentedSieve(a, b, segment_size);
else
segmentedSieve(b, a, segment_size);
if (t != 0)
cout << endl;
}
}
It seems range is uninitialized here:
void segmentedSieve(ll n, ll m, int segment_size) {
int i, j, s, p, range;
vb is_prime(range+1, true); // uninitialized range... !!
maybe you want
void segmentedSieve(ll n, ll m, int segment_size) {
int i, j, s, p, range;
range = floor(sqrt((double)n)); // This first...
vb is_prime(range+1, true); // then this
When possible you should initialize variables when you define them.
void segmentedSieve(ll n, ll m, int segment_size) {
int i, j, s, p; // no range here
int range = floor(sqrt((double)n)); // This first...
vb is_prime(range+1, true); // then this
In general you should postpone the definition of variables until you need them, i.e. don't define all variables in the start but do it as you need them.
p.s. As others have commented already - get rid of all that macro stuff...