Top 20 C++ Tricks for Competitive Programming

 

Though competitive programming can only be mastered with lots of practice and consistent hard work,  there are certain practices and tricks which can be your friend in this journey.  Here you will see some good tips and tricks of C++ programming language which will just help you to save a little time during the contests which might sometimes matter a lot.

 

1. Inbuilt GCD function:


 C++ has inbuilt GCD function and there is no need to explicitly code it. This seriously saves a lot of time during programming contests.

 Syntax__gcd(x, y);

Return Value :  0 if both m and n are zero,
else gcd of m and n.

 

 2. A single header file to rule them all


There are so many header files which you need to include in your programs like algorithm, iostream, vector etc. But we can avoid writing all of them separately. We use a single header file :

#include <bits/stdc++.h>
This library includes many of libraries we do need in contest like algorithm, iostream, vector and many more. You don't need to include anything else.

3.  Count set bits in a number


__builtin_popcount(x) is a builtin function in GCC compiler.It returns number of 1s (set bits) in the integer variable x.

e.g. __builtin_popcount(14) = 3 because 14 is '... 111 0' and has three 1-bits.

Similarly you can use __builtin_popcountl(x) & __builtin_popcountll(x) for long and long long data types.

 

4. endl vs /n

Using “\n” for adding new line breaks is much faster than using “endl” and can sometimes save you a TLE (Time Limit Exceeded) error during a programming contest.


5. Parsing input using stringstream

A stringstream class in C++ is a Stream Class to operate on strings. A stringstream associates a string object with a stream allowing you to read from the string as if it were a stream (like cin).
It has very important applications in programming like :

1. Extract individual words from a sentence or paragraph.
2. String to number conversion

and many more.

I have a separate post on stringstream and its applications. Check it out here:

=> stringstream in C++ : Detailed Usage and Applications with Examples


6. auto keyword


Using the auto keyword to declare datatypes can save a lot of time during programming contests.
When a variable is defined as auto, compiler can determine it's datatype on its own.
Example:

auto var1 = 500; // a will become 'int'
auto var2 = 1LL; // b will become 'long long'


7. Range based for loop


set<int> s = {10, 22, 30, 11};  

To traverse all the elements of set you would write something like this

for (set<int>::iterator it = s.begin(); it != s.end(); ++it)
    cout << *it << ' ';


C++ 11 introduced range based for loop and if we combine it with auto keyword we can simply iterate any container like this :

 for (auto it: s)
     cout << it << ' ';


8. Calculating the number of digits:

We can use logarithm instead of looping to find out the number of digits in a number.
Number_of_digits_in_N = floor(log10(N)) + 1;

 

9. Fast Input/ Output in C++

It is often recommended to use scanf/printf instead of cin/cout for faster input and output. However, you can still use cin/cout and achieve the same speed as scanf/printf by including the following two lines in the beginning of your main() function( before you take any input) :
ios_base::sync_with_stdio(false);
cin.tie(NULL);


Note : If you use this fast I/O technique, you’ll no longer be able to use printf or scanf in your program.

 

10. Using typedef and #define


Using typedef's for providing shorter names to different data types saves a lot of time in declaring variables in your program. You can directly use these shorter names for declaring variables.

typedef long long ll;
typedef pair pp;
typedef vector vec;


Eg. we can declare a pair<int,int> simply as pp p = make_pair(4,5);

Another way to shorten code is to define macros. A macro means that certain parts of the code will be changed before the compilation. macros are defined using the #define keyword.
For example, we can define the following macros:

#define F first;
#define S second;
#define pb push_back;
#define mp make_pair;


Now you can make a pair<int,int> in C++ as pp p = mp(4,5);

We can access the members of p by writing cout<<p.F<<" "<<p.S<<"\n";


11. Assign value by a pair of {} to a container


braces {} can be used to initialize various containers like pair, vector, deque etc very easily as shown below.

a.
pair<int, int> p;

Instead of : p = make_pair(3, 4);
you can just do this: p = {3, 4};

b. Initialize a vector as
vector<int> v;
v = {1, 2, 5, 2};


c. Initialize a set as
set<int> s;
s = {4, 6, 2, 7, 4};


12. More powerful set container : ordered_set 


Ordered set is a policy based data structure in g++ that keeps elements in sorted order. It performs all the operations as performed by the set data structure in STL(like find(), lower_bound() etc.) in O(log(n)) complexity and performs two additional functions with the same O(log(n)) complexity:

order_of_key (k) : number of items which are strictly smaller than k .
find_by_order(k) : k-th element in a set (counting from zero).

I have a separate detailed post on ordered_set and its applications. Check it out here:

=> Ordered Set in C++ : Policy Based Data Structure

 

13. inbuilt binary search


C++ STL provides us two functions which implement binary search for us, we just need to provide the value and the function automatically uses binary search to find iterator to the specified value in O(nlog n)

a. Iterator lower_bound (Iterator first, Iterator last, const val)

lower_bound returns an iterator pointing to the first element in the range [first,last) which has a value not less than ‘val’.

b. Iterator upper_bound (Iterator first, Iterator last, const val)
 
upper_bound returns an iterator pointing to the first element in the range [first,last) which has a value greater than ‘val’. 

 

14. inbuilt sort

Sorting is one of the most basic functions applied in many programming problems.
There is a builtin function in C++ STL by the name of sort().

Syntax:
sort(startaddress, endaddress)

startaddress: the address of the first element of the array
endaddress: the address of the next contiguous location of the last element of the array.

int a[10]= {1, 5, 8, 9, 6, 7, 3, 4, 2, 0};
 
sort(a, a+10);


We can use sort for vector using iterators;

vector<int> vec = {1, 5, 8, 9, 6, 7, 3, 4, 2, 0};

sort(vec.begin(), vec.end());


15. string as stack : pushback() and popback()


If you want to apply stack like functionality using string , you don't need to explicitly declare a stack of characters as string in C++ automatically provides that functionality but very few people are actually aware of this thing.

string s = "codingwithart";
s.push_back('N');         // pushes a new character at the end of string, s = "codingwithartN"
s.pop_back();            // pops the last character from the string, s = "codingwithart"


16. Bit manipulation using bitset


Using bitwise operators on multiple numbers can be a bit tricky. Therefore C++ provides us with bitset to carefully work on arrays of numbers.
A bitset is an array of bool but each bool value is not stored separately instead bitset optimizes the space such that each bool takes 1 bit space only, so space taken by bitset bs is less than that of bool bs[N] or vector bs(N). bitset provides us with a variety of predefined functions like  count, size, set, reset, and many more.
However, a limitation of bitset is, N must be known at compile time, i.e., a constant

For example :
bitset<8> set8; // 00000000
 
// setting first bit (or 6th index)
set8[1] = 1; // 00000010

cout << set8 << endl;   

// count function returns number of set bits in bitset
int numberof1 = set8.count();
 

// size function returns total number of bits in bitset
// so there difference will give us number of unset(0)
// bits in bitset
int numberof0 = set8.size() - numberof1;

// bset.set(pos, b) makes bset[pos] = b
 cout << set8.set(4, 0) << endl;

  


17. Initialize using memset()


We can use memset() to set all values as 0 or -1 for integral data types . It will not work if we use it to set as other values.It works for both 1D and 2D arrays.

Example :
int a[5][5];    
   
// all elements of A are zero
memset(a, 0, sizeof(a));



We can also use this for strings to set all characters as a particular character :

char str[] = "CodingWithArt";
memset(str, 'w', sizeof(str));
cout << str;
return 0;

Output :
wwwwwwwwwwwww


18. Functor in C++


You may have provided separate custom compare function for sort() in C++.  But you can also provide it for for containers like set, priority_queue etc but in a different way, using functor in C++.

// Sort a set of pairs by second value by functor
 
#define pii pair<int,int>

struct comp
{
    bool operator()(const pii &a, const pii &b)
    {
        return a.second<b.second;
    }
};
 
set<pii,comp> s; 

 
Now, whenever you insert some pair into this set, it will sort everything based on the second element primarily. Of course you could swap the first and the second element and avoid functor. In case there are cases where you need to do some complex sorting, functor can be of great help.


19. Check if a number is a power of 2


Simple solution to this problem is to repeated divide N by 2 if N is even. If we end up with a 1 then N is power of 2, otherwise not.
Time complexity of the above code is O(logN).

The same problem can be solved using bit manipulation.

Consider a number x. Now (x-1) will have all the bits same as x, except for the rightmost 1 in x and all the bits to the right of the rightmost 1.

For example:

Let, x = 4 = (100)2
x - 1 = 3 = (011)2

Properties for numbers which are powers of 2, is that they have one and only one bit set in their binary representation. If the number is neither zero nor a power of two, it will have 1 in more than one place. So if x is a power of 2 then x & (x-1) will be 0.

bool isPowerOfTwo(int x)
{
    // x will check if x == 0 and !(x & (x - 1)) will check if x is a power of 2 or not
    return (x && !(x & (x - 1)));
}


20. Find Least significant bit of a number


You can get the LSB of a number using a single line of code:


int LSB = x&-x;

(-x) is the two’s complement of x. (-x) will be equal to one’s complement of x plus 1.
Therefore (-x) will have all the bits flipped that are on the left of the rightmost 1 in x. So x & (-x) will return rightmost 1.

For example :
x = 10 = (1010)2
(-x) = -10 = (0110)2
x & (-x) = (1010)2 & (0110)2 = (0010)2


This brings us to the end of this article.  If you have any doubts please mention in the comments section.

Thank you for your patience reading. If you enjoyed this post, I’d be very grateful if you’d help it spread by emailing it to a friend, or sharing it on Whatsapp or Facebook.

😇Happy Learning!!


3 comments

Click here for comments
Costa Shul
admin
July 24, 2021 at 10:48 PM ×

"Using “\n” for adding new line breaks is much faster than using “endl”"
Are you sure?

Reply
avatar
Yash
admin
May 5, 2022 at 10:19 PM ×

For finding if a number is a power of two we can simply use a check: if(__builtin_popcount(num) == 1)
Just think, if there is any number which is a power of two then it can always be represented using a single active binary place.
2->0010, 16->00010000, 64->01000000
Anyways, great content.

Reply
avatar
Yash
admin
May 5, 2022 at 10:23 PM ×

@Costa_Shul
When you use '\n' it just inserts a new line, but when you use endl it inserts a new line as well as flushes the existing stream which takes extra time. That's the reason why '\n' is faster.

Reply
avatar