Ehab and subtraction CodeForces - 1088B (优先队列+思维)

给出一个序列 a . 我们会重复以下操作 k 次: 找出序列当中最小的、非零的数字,并输出。然后将序列中所有的非零数字减去这个数字,如果序列中的元素都是0,那么就只输出0.

Input

第一行是两个个整数 n and k (1 <= n,k <= 100000), 表示序列的长度和操作要执行的次数.

第二行包括有 n 个数 a[0], a[1], a[2]...... a[n-1] (1 <= a[i] <= 10^9), 表示序列中的元素.

Output

输出k次操作中,每个操作所选出的哪个数字.

Examples

Input

3 5
1 2 3

Output

1
1
1
0
0

Input

4 2
10 3 5 3

Output

3
2

Note

在第一个例子当中

第一步序列为 [1,2,3] 选出的数字是 1.

然后把序列中所有的数字 -1, 序列变为[0, 1, 2].

第二步序列为[0, 1, 2] 选出的数字是 1

然后把序列中所有的数字 -1, 序列变为[0, 0, 1].

第三步序列为[0, 0, 1] 选出的数字是 1

然后把序列中所有的数字 -1, 序列变为[0, 0, 0].

第四步,序列中所有数字为0, 输出0

第五步,序列中所有数字为0, 输出0

第二个例子中:

第一步: 序列为[10,3,5,3] 最小的非零数字是 3. 所有非零数字-3后序列为 [10, 0, 2, 0]

第二步: 序列为[7,0,2,0] 最小的非零数字是 2. 所有非零数字-2后序列为[5,0,2,0]

初看到题目,没有什么思路,拿什么写,因为具体的排序要求,需要将最小的数据排到最前面去处理,我们使用STL 优先队列重载函数来排序,使数据的最小值一直放在 队列的首位置,这样处理起来就会很方便。

处理掉这个问题后,怎么处理数据的全部减去一个值呢?如果你去遍历每一个数据,答案肯定是超时。这时数学思维就该上场了,怎么把二重循环改为一重的,我可以把每次的减值都记录下来,每一个数据都减去这个 sum ,就达到不用遍历 的效果。

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string.h>
#include<string>
const int maxn=100015;
int a[maxn];
#include<vector>
#include<queue>
typedef long long ll;

int main()
{
	priority_queue<int,vector<int>, greater<int> >mp;
	int n,k;
	cin>>n>>k;
	ll num;
	for(int i=0;i<n;i++)
	{
		cin>>num;
		mp.push(num);
	}
	ll sum=0;
	if(mp.top()==0)
	{
		mp.pop();
	}
	else
	{
		sum+=mp.top();
		mp.pop();
		cout<<sum<<endl;
	}

	int k1=1;

	while(!mp.empty()&&(k1<k))
	{
		ll c=mp.top()-sum;
		mp.pop();
		sum+=c;
		if(c<=0)
			continue;
		else
		{
			k1++;
			cout<<c<<endl;
		}
	}
	for(int i=k1;i<k;i++)
	{
		cout<<"0"<<endl;
	}


	return 0;
}

大体上就是这样,当遇到二重循环 解决问题时,想想可不可以 把二重循环 变为一重循环,降低时间复杂度。以更优的算法解决问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值