CF1213D Equalizing by Division

easy version

hard version

问题分析

直接从hard version入手。不难发现从一个数\(x\)能得到的数个数是\(O(\log x)\)的。这样总共有\(O(n\log n)\)个数。然后对每一种数开一个大根堆维护前\(k\)个就好了。

参考程序

#include <bits/stdc++.h>
using namespace std;

const int INF = 2147483647;
const int Maxn = 200010;
const int MaxAlpha = 200000;
int n, k, A[ Maxn ], Sum[ Maxn ];
priority_queue< int > Pq[ Maxn ];
int main() {
	scanf( "%d%d", &n, &k );
	for( int i = 1; i <= n; ++i ) scanf( "%d", &A[ i ] );
	sort( A + 1, A + n + 1 );
	for( int i = 1; i <= n; ++i ) {
		int t = 0;
		if( Pq[ A[ i ] ].size() == k ) Sum[ A[ i ] ] -= Pq[ A[ i ] ].top(), Pq[ A[ i ] ].pop();
		Pq[ A[ i ] ].push( 0 );
		while( A[ i ] ) {
			++t; A[ i ] /= 2;
			if( Pq[ A[ i ] ].size() < k ) Pq[ A[ i ] ].push( t ), Sum[ A[ i ] ] += t;
			else
				if( Pq[ A[ i ] ].top() > t ) {
					Sum[ A[ i ] ] -= Pq[ A[ i ] ].top(), Pq[ A[ i ] ].pop();
					Sum[ A[ i ] ] += t; Pq[ A[ i ] ].push( t );
				}
		}
	}
	int Ans = INF;
	for( int i= 0; i <= MaxAlpha; ++i ) 
		if( Pq[ i ].size() == k )
			Ans = min( Ans, Sum[ i ] );
	printf( "%d\n", Ans );
	return 0;
}

posted @ 2019-09-06 20:25  chy_2003  阅读(192)  评论(0编辑  收藏  举报