Repeatedly keep removing 2 smallest elements and add its sum back to the list and return newly inserted elements' total
#include &lt;sstream&gt;


Only include what is necessary.



    for(int i=0 ; i&lt;n ; i++) { ... }


Use range-based for.

    std::cout &lt;&lt; ... &lt;&lt; std::endl;


Avoid std::endl.



void printArray(std::vector&lt;int&gt; &amp;arr, int n) { ... }
                                       ^^^^^
int main() {
    int n = arr.size();
          ^^^^^^^^^^^^
    printArray(arr,n);
                   ^


You have an implicit conversions from std::vector::size_type to int when you initialize n and pass an int argument to parameter n.



    printArray(arr, n);
    heapSort(arr, n);


std::vector carries its size. You do not have to capture it in a variable and pass it.

    int n = arr.size();
    while (arr.size() &gt; 1) {
        heapSort(arr, n);
        arr.erase(...);
        arr.push_back(...);
    }


With each iteration of the loop, you pop 2 elements and push 1 element reducing the size of arr by 1. n is a local copy of arr.size() and is never updated. This results in out-of-bounds index access in your sort functions after the first iteration of this loop.

As for your issues with excessive calls to heapify(), you are calling heapSort() on every iteration. heapSort() takes a sequence in any order, sorts all of the values into heap order, then sorts all of the values again into sequential sorted order. This is done so you can operate on the two minimum values at the same time. Instead of fully sorting the sequence on every iteration, you can take a partial sort approach. Maintain the sequence in heap order by sifting values around as you mutate the sequence. Finding each minimum values is simply a swap and a sift down. Repairing the heap order on insertion is simply a sift up. Which brings me to know your &lt;algorithm&gt;s. The C++ standard library provides heap operations (is, make, push, pop, sort).

    // Sort into min-heap order
    std::make_heap(arr.begin(), arr.end(), std::greater()) 

    while (arr.size() &gt; 1) {
        // rotate out the 1st min keeping heap order intact
        std::pop_heap(arr.begin(), arr.end(), std::greater());
        const auto first = arr.back();
        arr.pop_back();

        // rotate out the 2nd min keeping heap order intact
        std::pop_heap(arr.begin(), arr.end(), std::greater());
        const auto second = arr.back();
        arr.pop_back();

        const auto sum = first + second;
        ans += sum;

        // Move the inserted value into its heap order position
        arr.push_back(sum);
        std::push_heap(arr.begin(), arr.end(), std::greater());
    }


std::priority_queue helps clean up some of the duplication.

    std::priority_queue min_heap{std::greater(), std::move(arr)};
    while (min_heap.size() &gt; 1) {
        const auto first = min_heap.top();
        min_heap.pop();
        const auto second = min_heap.top();
        min_heap.pop();

        const auto sum = first + second;
        ans += sum;
        min_heap.push(sum);
    }