Equalizing by Division 思维

The only difference between easy and hard versions is the number of elements in the array.

You are given an array a consisting of n integers. In one move you can choose any ai and divide it by 2 rounding down (in other words, in one move you can set ai:=⌊ai2⌋).

You can perform such an operation any (possibly, zero) number of times with any ai.

Your task is to calculate the minimum possible number of operations required to obtain at least k equal numbers in the array.

Don’t forget that it is possible to have ai=0 after some operations, thus the answer always exists.

Input
The first line of the input contains two integers n and k (1≤k≤n≤2⋅105) — the number of elements in the array and the number of equal numbers required.

The second line of the input contains n integers a1,a2,…,an (1≤ai≤2⋅105), where ai is the i-th element of a.

Output
Print one integer — the minimum possible number of operations required to obtain at least k equal numbers in the array.

Examples
Input
5 3
1 2 2 4 5
Output
1
Input
5 3
1 2 3 4 5
Output
2
Input
5 3
1 2 3 3 3
Output
0

思路:
首先统计出每个数字出现的次数,如果有符合条件的,直接输出;没有的话,对数据进行从小到大排序;然后对每个数字进行折半处理,并且记录下来到大每一个数字时所用的操作次数(因为对数据进行了排序,所以操作k次能得到m个数字n这时候的k是最小的),然后记录达到符合条件的数字需要的操作是多少,去所有符合条件的数字对应操作数的最小值;

#include 
#include 
#include 
#include 
#include 

using namespace std;
const int maxx=1e6+7;
typedef long long ll;
#define INF 0x3f3f3f3f;
map<int,int> mpp;
map<ll,int> mp;
int a[maxx];
int main()
{
    int n,k;
    cin >>n>>k;
    int flag=0;
    for(int i=0;i<n;i++)
    {
        cin >>a[i];
    }
    for(int i=0;i<n;i++)
    {
        mpp[a[i]]++;
        if(mpp[a[i]]==k)
        {
            flag=1,cout <<0<<endl;
            break;
        }
    }
    sort(a,a+n);
//    for(int i=0;i
//    cout <
    int temp=INF;
    for(int i=0;i<n;i++)
    {
        int x=a[i]/2;
        int ans=1;
        while(x)
        {
            int a=mpp[x]++;
            mp[x]+=ans;
            int b=mp[x];
            if(mpp[x]==k)
            {
                if(temp>mp[x])
                {
                    temp=mp[x];
                }
            }
            x/=2;
            ans++;
        }
    }
    if(flag==0) cout <<temp<<endl;
    return 0;
}

你可能感兴趣的:(思维)