Rating changes for last rounds are temporarily rolled back. They will be returned soon. ×

redgulli's blog

By redgulli, history, 4 years ago, In English

I have been attempting this problem on codechef.

LINK TO PROBLEM STATEMENT

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;
}

  • Vote: I like it
  • -5
  • Vote: I do not like it

»
4 years ago, # |
  Vote: I like it +2 Vote: I do not like it

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)