题目描述:
血魔遇到了N个敌人。初始血魔生命值为M,每秒钟血魔的生命值会减少1。如果血魔的生命值变为0,血魔会立刻消失,但在此之前他可以击杀敌人来恢复生命值。对于第i个敌人需要攻击Ti次才能杀死,血魔每秒钟可以攻击一次,每秒钟血魔可以攻击任意一个敌人,并且每次攻击可以同时击中任意多个敌人。敌人一共有K种类型,对于每种类型的敌人,血魔最多只能杀死一个。血魔在进行过所有攻击后,他可以立刻恢复他所杀死敌人的最小生命值,在恢复过后不能再继续进行攻击(如果血魔生命值变为0的瞬间恢复生命值,血魔不会死亡)。现在血魔想知道,他是否能杀死K个敌人,如果能的话,那么杀死K个敌人后,生命值最高能为多少?
输入说明:
第一行3个整数N,M,K,分别表示敌人数量,血魔初始的生命值,敌人类型数。
接下来N行,每行三个整数Hi,Ti,Ci,分别表示第i个敌人的生命值,需要攻击的次数和类型。
1 <= Ci <= K <= N <= 105
1 <= Hi,Ti,M <= 109
保证每种类型的敌人至少有一个。
输出说明:
如果不能杀死K个敌人输出-1,否则输出生命值最大值。
输入样例:
样例1
2 5 2
1 2 2
4 5 1
样例2:
5 4 2
4 2 1
1 1 1
4 1 1
3 2 2
1 1 2
样例3:
3 5 3
5 2 1
1 6 2
3 2 3
输出样例:
样例1:
1
样例2:
5
样例3:
-1
解题思路:
本题对时间复杂度的要求比较高,我们要杀死K个敌人,要取可以消灭的每种类型中的血量最大值。 题目告诉我们,杀死K个敌人后,我们可以吸收杀死的敌人的最小生命值
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
typedef long long ll;
int n,m,k;
struct node{
int h,t,c;
};
inline bool cmp(node x,node y){
return x.t<y.t;
}
void slove(){
cin>>n>>m>>k;
vector<node>a(n);
for(auto &[h,t,c]:a)cin>>h>>t>>c,c--;
sort(a.begin(),a.end(),cmp);
vector<int>mx(k,0);
priority_queue<pii,vector<pii>,greater<pii> >q;//从小到大
int ans=0,cnt=k;
for(const auto &[h,t,c]:a){
if(t>m)
break;
int mn=1e9;
if(h>mx[c]){
q.push({h,c});
if(mx[c]==0)
cnt--;
mx[c]=h;
}
while(q.size()){
auto [hh,cc]=q.top();
if(mx[cc]>hh)
q.pop();
else{
mn=hh;
break;
}
}
if(!cnt){
ans=max(ans,m-t+mn);
}
}
if(!cnt)
cout<<ans<<endl;
else
cout<<-1<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
slove();
return 0;
}