codeforces1213D2 - Equalizing by Division (hard version)(排序)

D2. Equalizing by Division (hard version)
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
The only difference between easy and hard versions is the number of elements in the array.

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

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

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

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

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

The second line of the input contains ? integers ?1,?2,…,?? (1≤??≤2⋅105), where ?? is the ?-th element of ?.

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

Examples
inputCopy
5 3
1 2 2 4 5
outputCopy
1
inputCopy
5 3
1 2 3 4 5
outputCopy
2
inputCopy
5 3
1 2 3 3 3
output

题意: 操作是把一个数字除以2向下取整。最少多少次操作使得至少k个数字相等。
思路: 果然要多打比赛,这道题都演了。
这不是直接排个序然后算贡献吗?比赛的时候写d1看到了50的数据范围心想乱搞就可以了,结果50是个数,a[i]数据还是2e5。。。然后没了~~~~(>_<)~~~~

#include 
#include 
#include 
#include 
#include 

using namespace std;
typedef long long ll;

int a[200005];
int vis[200005];
int num[200005];
int ans[200005];

int main()
{
    int n,k;scanf("%d%d",&n,&k);
    
    int flag = 0;
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&a[i]);
        vis[a[i]]++;
        if(vis[a[i]] >= k)flag = 1;
    }
    if(flag){printf("0\n");return 0;}
    
    memset(vis,0,sizeof(vis));
    memset(num,0,sizeof(num));
    memset(ans,0x3f3f3f3f,sizeof(ans));

    sort(a + 1,a + 1 + n);
    for(int i = 1;i <= n;i++)
    {
        int x = a[i];
        int cnt = 0;
        while(x)
        {
            vis[x]++;
            num[x] += cnt;
            cnt++;
            if(vis[x] == k)
            {
                ans[x] = num[x];
            }
            x /= 2;
        }
    }
    int anss = 0x3f3f3f3f;
    for(int i = 1;i <= 200000;i++)
    {
        anss = min(anss,ans[i]);
    }
    printf("%d\n",anss);
    return 0;
}

你可能感兴趣的:(#,codeforces)