给出一个序列 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;
}
大体上就是这样,当遇到二重循环 解决问题时,想想可不可以 把二重循环 变为一重循环,降低时间复杂度。以更优的算法解决问题。