1 条题解
-
7
因为总伤害固定,免除的伤害越多,实际受到的伤害就越少。易得,将药水用于最大的 场战斗上是最优的。
所以对于任意一个前缀,我们只需要选出其中伤害最大的至多 个敌人,用药水免除它们的伤害。
具体地,从左到右遍历每个敌人,维护一个总伤害
sum,以及一个小根堆,堆里存当前选中的、准备用药水免除的伤害值,堆的大小不超过 。同时用heal记录堆中元素的总和(即免除的总伤害)。对于每个敌人 :
- 把 加入总伤害
sum。 - 如果堆的大小小于 ,直接放入堆,
heal += a_i。 - 否则,如果 比堆顶(当前免除的最小伤害)大,就弹出堆顶,放入 ,并更新
heal。 - 然后检查实际受到的伤害
sum - heal。如果它 ,说明傻鹿会在第 个敌人处倒下,最多只能击败前 个,输出i-1并结束。 - 如果遍历完所有敌人都没有倒下,输出
n。
时间复杂度:每组数据 ,总 ,可以通过。
参考代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=1e5+5; ll n,m,k; ll a[N]; void solve(){ cin>>n>>m>>k; for(int i=1;i<=n;i++) cin>>a[i]; priority_queue<ll,vector<ll>,greater<ll>> q; ll sum=0,heal=0; for(int i=1;i<=n;i++){ sum+=a[i]; if(k>0){ if(q.size()<k){ heal+=a[i]; q.push(a[i]); }else if(a[i]>q.top()){ heal-=q.top(); q.pop(); q.push(a[i]); heal+=a[i]; } } if(sum-heal>=m){ cout<<i-1<<'\n'; return; } } cout<<n<<'\n'; return; } int main(){ int T;cin>>T; while(T--) solve(); } - 把 加入总伤害
信息
- ID
- 2738
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- (无)
- 递交数
- 19
- 已通过
- 12
- 上传者