题目大意:
给你三个数n,k,x
n代表给n个数
k代表你能在这些数字中再赛几个数字
x代表如果n个数中两两相邻的数绝对值之差<=x的时候就算一个组
问你你最少能分几个组(自由调整数字顺序
思路:
差分+贪心
首先对数字排序
计算出两两相差的值
然后计算需要赛几个数字才能让不是一组的变成一组
这里计算塞几个数字的公式是ceil(1.0*差值/x)-1 (ceil是向上取整函数
然后保存下来,sort一下
每次用k减去最小数字,如果不能减的时候就让一直答案+1即可
用map也可以,一开始想用map的直接让下标等于赛多少数字,值为有多少个这样的数字,但是中间变量没开long long而且map不确定遍历方式是不是按下标从小到大遍历的就换了一种方式
后来比赛结束问了一下是按从小到大遍历的,就是没开long long 的问题
但是跑的没我想象的比sort快- -,可能常数大的原因吧
两种代码都贴一下
用map的代码(这里用ceil进行判断的方法有错(精度问题),后面被人hack了)
(第二种是对的,可以看第二种代码的判断方式)
#include <iostream>
#include <algorithm>
#include <map>
#include <math.h>
using namespace std;
typedef long long ll;
ll a[200010];
ll d[200010];
map<ll,ll>mp;
int main()
{
ll n,k,x;
cin>>n>>k>>x;
for(int i=0;i<n;i++)cin>>a[i];
sort(a,a+n);
for(int i=1;i<n;i++){
d[i]=a[i]-a[i-1];
ll b=ceil(1.0*d[i]/x)-1;
if(b>0)
mp[b]++;
}
ll ans=1;
for(auto &it:mp){//map遍历
if(k-it.second*it.first>=0){
k-=it.second*it.first;
}else{
ans+=it.second-k/it.first;
k=0;
}
}
cout<<ans<<endl;
return 0;
}
存数组里然后排序的
#include <iostream>
#include <algorithm>
#include <map>
#include <math.h>
using namespace std;
typedef long long ll;
ll a[200010];
ll d[200010];
ll t[200010];
map<ll,ll>mp;
int main()
{
ll n,k,x;
cin>>n>>k>>x;
for(int i=0;i<n;i++)cin>>a[i];
sort(a,a+n);
int j=0;
for(int i=1;i<n;i++){
d[i]=a[i]-a[i-1];
if(d[i]>x){
ll b=(d[i]-1)/x;
t[j++]=b;
}
}
ll ans=1;
sort(t,t+j);
for(int i=0;i<j;i++){
if(k>=t[i])k-=t[i];
else{
ans++;
}
}
cout<<ans<<endl;
return 0;
}