CCPC-Wannafly Winter Camp Day5 (Div2, onsite) C Division 数据结构-优先队列

本文探讨了一道算法题目,目标是在限定操作次数内,通过将数列中的元素除以2并向下取整的方式,使数列总和达到最小值。文章提供了详细的解题思路,利用优先队列实现高效求解,并附带完整的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

 

你有一个数列a_1, a_2, \dots, a_na1​,a2​,…,an​。你可以进行这样的一次操作,每次选择数列中其中一个数然后将其除22下取整,也就是选择一个数a_iai​,变成\lfloor a_i/2 \rfloor⌊ai​/2⌋。

请问对这些数字进行不超过kk次操作,这些数字的总和最小值可能是多少。

输入描述

 

第一行两个整数 n, k(1\leq n\leq 10^5, 0\leq k\leq 10^9)n,k(1≤n≤105,0≤k≤109),表示数字个数和操作个数。

接下来nn行,一共nn个整数a_1,a_2,\dots, a_na1​,a2​,…,an​,保证1\leq a_i \leq 10^91≤ai​≤109。

输出描述

 

一个数字表示答案。

样例输入 1 

5 3
2 4 7 9 7

样例输出 1

16

虽然这个题很简单,就是k次队最大数进行除2操作。但是不得不说这个题的数据水了。

因为如果输入  1  1e9,会进行1e9次除2操作,会tle。但是我们知道,1e9只需要除32次就可以是0

所以我们用优先队列每次弹出最大值。但是如果队首为空的时候,就不需要再继续除2操作了。break输出即可。

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<string> 
#include<queue>
#define PI 3.1415926
#define zero(x) (((x)>0?(x):-(x))<eps)
using namespace std;
typedef  long long ll;
const double eps = 1e-8;
const int maxn = 1e5 + 100;


int main()
{
	int n, k;
	int u;
	scanf("%d%d", &n, &k);
	priority_queue<int>pq;
	for (int i = 1; i <= n; i++)
	{
		int u;
		scanf("%d", &u);
		pq.push(u);
	}
	while (k != 0)
	{
		u = pq.top();
		if (u == 0)  //队首等于0的时候,不需要再除2了
		{
			break;
		}
		pq.pop();
		u = u / 2;
		pq.push(u);
		k--;
	}
	ll sum = 0;
	while (!pq.empty())
	{
		sum += pq.top();
		pq.pop();
	}
	printf("%lld\n", sum);
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值