dp_{i,j} 表示为前 i 个数全取到 j 的最少操作次数。因为数组存不下,但是最多要存的数也就 nlogn 个,实际上更少,所以这里可以采用 unordered_map,且每个数只能从上一个数能取到的转移过来,如果上一个数取不到 x 那么也就没必要转移了,最后就看 dp_{n,x}的最小值即可。

#include<bits/stdc++.h>

using namespace std;

using i64 = long long;

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int n;
	cin >> n;

	vector<int> a(n);
	for (int i = 0; i < n; i ++) {
		cin >> a[i];
	}

	vector<unordered_map<int, int>> dp(n);

	for (int i = 30; i >= 0; i --) {
		auto x = a[0] >> i;
		if (!dp[0].count(x)) {
			dp[0][x] = i;
		} else {
			dp[0][x] = min(dp[0][x], i);
		}
	}

	for (int i = 1; i < n; i ++) {
		for (int j = 30; j >= 0; j --) {
			auto x = a[i] >> j;
			if (dp[i - 1].count(x)) {
				if (!dp[i].count(x)) {
					dp[i][x] = dp[i - 1][x] + j;
				} else {
					dp[i][x] = min(dp[i - 1][x] + j, dp[i][x]);
				}
			}
		}
	}

	int ans = INT_MAX;
	for (auto [_, num] : dp[n - 1]) {
		ans = min(ans, num);
	}

	cout << ans << "\n";

	return 0;
}