I wouldn't say, "easy to understand" but it's an awesome idea!

I'll try to explain for the others who sees this solutions. As usual (but not always), in binary tree problems, each node conforms to the constraints of the whole tree. Let's take a look at some node R and mark its depth (the length of the path from the node to the deepest leaf) with D.

There are two options (assuming we are talking about a complete tree):

The left sub-tree is full (all the levels, including the last, are full) and of depth D-1, and the right sub-tree is complete (all levels, except the last, are full, and last is "left-justified").
The right sub-tree is full, and of depth D-2 and the last partial level is on the left sub-tree.

What do we have to do in each case?

The number of nodes in a full tree of depth D is [ 2^(D+1) - 1 ], so [2 ^ D] is actually the number of nodes in the sub-tree, added 1 for the root.

In the code, it seems like he calculates the depth of the left and right sub-trees, but because it starts from 0 and not (-1) this is actually the depths from the root.

Calculate the number of nodes in the left sub-tree, and recurse on the right sub-tree (it's a complete tree too)
Similarly, calculate the number of nodes in the right sub-tree and recurse on the left sub-tree.

Things to note:

These lines:

if(l_level==r_level) return (1<<l_level)+countNodes(l_level-1,root->right);
return (1<<r_level)+countNodes(l_level-1,root->left);

Can be replaced by that:

return (1<<r_level)+countNodes(l_level-1,l_level==r_level ? root->right : root->left);

And that's tail recursion now! (which should more efficient, but for some reason doesn't produce a faster algorithm).

I converted this code to be iterative (tail recursion is usually easy to convert to iterative) which yields a slightly better performance (~80ms):

class Solution {
public:
int countNodes(TreeNode* root) {
if(!root) return 0;
auto l = root->left;
int l_level = 0, r_level = 0;
// root depth from the left node
while(l) {l_level++;l=l->left;}
int completeNodes = 0;
while (root) {
auto r = root->right;
// root depth from the right node
r_level = 0;
while(r) {r_level++;r=r->left;}
// this is actually the right or left subtree size, added 1 for the root
completeNodes += (1 << r_level);
// if the levels are equal, it means the partial last level is on the right subtree
root = l_level == r_level ? root->right : root->left;
// we don't have to calculate the left-side level again
l_level--;
}
return completeNodes;
}
};