I have been attempting this problem on codechef.
My approach:
Sort the numbers in descending numbers.
Segregate the numbers into buckets based on Most Significant Bits.
Process the buckets in decreasing order.
Once all the elements of a bucket have been divided by 2, merge them into the previous bucket and move backwards to the previous bucket.
However this gives wrong answer. What is wrong with this approach ?
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> merge(vector<ll>a,vector<ll>b){
int i=0;
int j=0;
vector<ll>ans;
while(i<a.size() && j<b.size()){
if(a[i] > b[j])
{
if(a[i]>0)
ans.push_back(a[i]);
i++;
}
else{
if(b[j]>0)
ans.push_back(b[j]);
j++;
}
}
while(i<a.size()){
if(a[i]>0)
ans.push_back(a[i]);
i++;
}
while(j<b.size()){
if(b[j]>0)
ans.push_back(b[j]);
j++;
}
return ans;
}
int main() {
// your code goes here
int N,M;
cin>>N>>M;
vector<ll>arr(N);
for(int i=0;i<N;i++)
cin>>arr[i];
vector<ll>steps(M);
for(int i=0;i<M;i++){
cin>>steps[i];
}
vector<vector<ll>>buckets(64);
for(int i=0;i<64;i++){
vector<ll>tmp;
buckets[i]=tmp;
}
sort(arr.begin(),arr.end(),std::greater<ll>());
for(int i=0;i<N;i++){
int pos=0;
int num=arr[i];
while(num > 0){
num=num >> 1;
pos++;
}
buckets[pos].push_back(arr[i]);
}
int cur=0;
int count=0;
for(int i=63;i>=0;i--){
for(int j=0;j<buckets[i].size();j++){
count++;
if(cur<steps.size() && count==steps[cur]){
cur++;
cout<<buckets[i][j]<<endl;
}
buckets[i][j]=buckets[i][j] >> 1;
}
if(i>=1)
{
buckets[i-1]=merge(buckets[i],buckets[i-1]);
}
}
return 0;
}
Don't do such complecated merge, instead just simulate the process.
Put numbers in a map denoting the frequency. Then iterate the map from biggest number to smallest number. In every step all the numbers of current bucket are removed, and put into the bucket n/2.
In every such step fill ans for Q falling into the current interval of steps. (sort Q[] beforehand)