前几日刷到一个算法题,学到不少,遂整理下来。
来源:牛客网
问题描述:
身为新时代热爱种树的绿色青年,小明手里有 n 个树苗,第 i个树苗长成需要 Ai 天的时间, 为了让树更快长成,小明在夜里与骷髅射手激战,最后做了 m 个骨粉,一个骨粉可以缩短 1 天的生长时间, 问这 n 棵树苗最快几天长成树。
输入描述:
第一行有两个正整数,n (1≤n≤10^5), m (0≤ m≤ 10^9),表示树苗的个数和小明所获得的骨粉数。
第二行有 n 个正整数,表示第 i 课树苗的生长所需时间 Ai (1≤n≤10^9)。
输出描述:
输出一个正整数表示树苗最少需要多长时间全部长成树。
示例输入:
4 3
7 3 4 7
示例输出:
6
思路:
1.输入数据,如果总生长天数小于或等于骨粉数,骨粉完全够用,输出零;接下来处理骨粉不够用的情况。
2.先将树的生长时间排序(大到小),开始削头法撒骨粉。
3.k = 0指向最大的生长时间(第一个),计算k与k+1的差cha,cha * count(count = k -1;表示目前数到第几棵树)就是骨粉要完全削去所有拥有最大生长时间的数,使其最大生长时间等于第二大生长时间所需要的最小骨粉数量,bone = bone - cha* count,直到bone <= 0。
4.bone加回来刚刚减去的值,bone/count 表示可以让最大生长天数减少几天,输出相减的值。
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
long long treeN, bone;
long long treeT[100010];
long long sum = 0;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin.tie(0);
cout.tie(0);
cin>>treeN>>bone;
for(long long i = 0; i < treeN; i++){
cin>>treeT[i];
sum = sum + treeT[i];
}
if(sum <= bone){cout<<"0";return 0;}//骨粉完全够用
sort(treeT, treeT + treeN, greater<int>());
unsigned int k = 0;//指针k
unsigned int count = 0;
long long cha = 0;
while(bone >= 0){
count++;
cha = (treeT[k] - treeT[k+1])*count;
//if(cha == bone) {cout<<treeT[k+1];return 0;}//bone = 0;可以不写,直接删掉
bone = bone - cha;
k++;
if(k == treeN - 1){cout<<treeT[k];return 0;}
}
k--;
bone = bone + cha;
cout<<treeT[k]- (bone/count);
return 0;
}