题解:AcWing 4495. 数组操作

题面

link

分析

首先,本题数据量较大(1 ⩽ \leqslant n , k n,k n,k ⩽ \leqslant 1 0 5 10^{5} 105),暴力是不可能暴力的。
不难看出, k k k次操作无法避免,因此要减少找出 x x x并将所有元素减去 x x x的时间。具体的方式:

  • c n t cnt cnt数组记录 x x x的总和,用 a i a_{i} ai原本的值减去当前 c n t cnt cnt的值就是当前操作后 a i a_{i} ai的值,省去全部减 x x x的时间。
  • 用一个从小到大的优先队列 q q q储存 a a a,当 a i − c n t ⩽ 0 a_{i}-cnt\leqslant0 aicnt0直接 p o p pop pop x x x就是q.top(),省去查找时间。

代码

#include <iostream>
#include <queue>
using namespace std;

const int N=10010;
int n,k,x,cnt;
priority_queue<int, vector<int>, greater<int> >q;//注意要加空格,不然会被报错
int main()
{
	cin>>n>>k;
	for(int i=0;i<n;i++)
	{
		cin>>x;
		if(x!=0) q.push(x);//已经是0了就不用管了
	}
	while(k--)
	{
		if(q.empty()) cout<<0<<endl;//没有非零的了就输出0
		else//注意下面三行的顺序,不能颠倒
		{
			cout<<q.top()-cnt<<endl;//注意是q.top()不是q.front(),因为优先队列的原理是堆,堆顶“顶”就是top
			cnt+=q.top()-cnt;
			while(q.top()-cnt<=0&&!q.empty()) q.pop();//一定要记得判断q为不为空,不然会死循环
		}
	}
	return 0;
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值