https://www.acwing.com/problem/content/5440/
目录
- 简述题目
- 时间复杂度分析
- 总代码
题目分析:
一共有n头牛,m个糖,给牛轮流吃糖,当前糖被吃完后就换下一个糖,每一个糖都从第一头牛开始吃,牛吃完糖后会长高,所长的高度是牛所吃糖的长度,问把全部糖吃完以后,每头牛都变成了多高?(注意糖是自上而下悬挂在天花板上的,牛只能吃掉比自己低的部分的糖)
时间复杂度分析:
该题目暴力思路很好想,暴力思路时间复杂度第一眼会以为是n2过不了,但是仔细分析时间复杂度后会发现时间复杂度其实是nlogn就能过了,下面我们来分析一下时间复杂度:
每一个糖的第一口都是第一头牛吃,我们光分析一下第一头牛就行,第一头牛吃糖有两种情况,第一种情况是牛比糖高,牛一口就把糖吃完了,那么后面的牛也就不用吃了,直接break就行;第二种情况是糖比牛高,那么牛就可以吃掉它身高长的糖,使得自己身高成为之前的二倍,我们假设这头牛能一直吃,身高一直乘二,我们注意到数据范围中说:糖最高是1e9,而2的30次方就已经超
过1e9了,所以一头牛最多只能吃30次,30次后后面的牛就都不用考虑了。因此时间复杂度是nlogn。
总代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+20;
typedef long long ll;
int b[N];
ll a[N];
int n,m;
int main()
{
cin >> n>>m;
for(int i=0;i<n;i++)
cin >> a[i];
for(int i=0;i<m;i++)
cin >> b[i];
for(int i=0;i<m;i++)//遍历每个糖
{
int t=0;//糖是自上而下悬挂的,我们记录糖的最底部的高度,一开始糖没被吃最底部是0
for(int j=0;j<n;j++)//遍历每头牛
{
if(t>a[j])continue;//糖最底部的比牛高,那牛就吃不了,下面就不用考虑了
int sum=min((ll)b[i],a[j])-t;//sum是牛所吃的糖的长度,此时有两种情况
//1是牛比糖最高处还要高,那么sum=b[i]-t(最多只能吃剩下的全部的糖)
//2是牛介于最高处和t之间,那么sum=a[i]-t
t+=sum;//牛吃掉了sum,糖最底部的高度就会上升sum
a[j]+=sum;//牛吃糖后张个
if(t>=b[i])break;//糖被吃完了,后面的牛就不用考虑吃不吃了
}
}
for(int i=0;i<n;i++)
{
cout << a[i]<<endl;
}
}