problem:

you are given an array of n integers. In one operation, you can choose two indices i and j, and delete arr[i] if 2* arr[i] ≤ arr[j]. You cannot use a particular element more than once.

Return the minimum size of the array after performing the operation any number of times.

examples:

N = 4 arr = [1, 2, 3, 4]

operation 1: choose 1 and 3. The array becomes [2, 3, 4] operation 2: choose 2 and 4. The array becomes [3, 4]

the answer is 2.


Let me know if you think I am wrong by email. I appreciate any possible learning.

Solution:

Notice that the minimum size you can ever reach after any number of operations is the half the initial size N.

look at all elements as candidates for removal for a moment. 1 can be removed by any number in [2, inf). 2 can be removed by any number in [4, inf). for 3 the range is [6, inf) and for 4 the range is [8, inf). Note that smaller elements have greater ranges than bigger ones.

This should hopefully lead you to the fact that if x < y, then x can always match with elements that y can match with, but the same cannot necessarily be said for y.

Take this example:

1 2 3 4

2 can only match with 4, but 1 can match with 2, 3, and 4

So, larger elements should be considered before smaller elements. Since only N/2 elements can be removed in the best case, the smallest 50% of numbers should be considered in descending order.

#include<iostream>
#include<vector>
#include<algorithm>


using namespace std;

#define REP(i,N) for (int i = 0;i < N;++i)

#define ll long long

int main() {
	int N;
	cin >> N;

	vector<int> A(N);

	REP(i, N) cin >> A[i];

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

	int j = N - 1;
	int cnt = 0;

	for (int i = N / 2 - 1;i >= 0;--i) {
		if (2 * A[i] <= A[j]) {
			++cnt;
			--j;
		}
	}

	cout << N - cnt << endl;
}