step1:创建一个字典map,其key表示数组中的元素,value表示该元素在数组中出现的个数。我们维护所有key中的最小值minK。

step2:由于map底层是红黑树,其key是按照从小到大排列的,因此我们很容易获得其最大的key。对这个key,先将其从map中移除,然后对该key值进行二进制右移的操作(即题目中的除以2向下取整),每一次操作,实际的操作数为key对应的value。经过若干次操作,直到key的值小于等于minK。此时将新的键值对key-value更新到map中。

step3:重复step2,直到map中只剩下一个key-value为止。

#include <iostream>
#include <map>
using namespace std;

int main() {
    int n, a, minK = INT32_MAX;
    cin >> n;
    map<int, int> mp;
    for (int i = 0; i < n; ++i) {
        cin >> a;
        ++mp[a];
        minK = min(minK, a);
    }
    int ans = 0;
    while (mp[minK] != n) {
        auto kv = *mp.rbegin();
        int key = kv.first;
        int value = kv.second;
        mp.erase(key);
        while (key > minK) {
            key >>= 1;
            ans += value;
        }
        mp[key] += value;
        minK = min(minK, key);
    }
    cout << ans;
}