题意
- n块小石头,1块大石头,大石头生命值m,撞碎每块小石头先扣除a滴血,然后再回复b滴血,能否使n块小石头在一定的顺序下被吃掉而不死(m<0)
思路
-
一个很贪的贪心
-
由于我们希望尽可能撞碎尽可能多的石头,所以第一步贪心是把所有小石头分为三类,先撞使稳定性提升的,再撞使稳定性不变的,最后处理使稳定性下降的
-
对于使稳定性提升的要先处理扣血少的,因为初始血量可能不够处理扣血多的
-
对于不改变稳定性的无所谓处理的先后顺序,只要遇到比总血量大的就直接死了
-
对于使稳定性下降的展开贪心的几次思考
1.先吃扣的多的:
但有可能啃了硬的不够硬的也啃不动了
2.先吃性价比高的:
有特例:总共7滴血,第一组:1 0,第二组7 5过不了
3.先吃回复的多的:
因为我们希望尽可能多撞几个,也就是撞完后活着,那么对于任意相邻的两个,我们要使得撞完第一个还能撞第二个,即保证对于a1,b1,a2,b2,如果12为更优的顺序,则有b1-a1-a2>b2-a2-a1,化简可得b1>b2,也就是恢复力高的往前排
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef struct {
int a,b;
}E;
E ener[505050];
int cmp0(E x,E y){return (x.b-x.a)>(y.b-y.a);}
int cmp1(E x,E y){return x.a<y.a;}
int cmp3(E x,E y){return x.b>y.b;}
int main(){
int t,n;
long long m;
scanf("%d",&t);
while(t--){
int jg=1;
scanf("%d%lld",&n,&m);
int cnt1=0,cnt2=0;
for(int i=0;i<n;i++){
scanf("%d %d",&ener[i].a,&ener[i].b);
if(ener[i].a<ener[i].b)cnt1++;
else if(ener[i].a==ener[i].b)cnt2++;
}
sort(ener,ener+n,cmp0);
sort(ener,ener+cnt1,cmp1);
sort(ener+cnt1+cnt2,ener+n,cmp3);
for(int i=0;i<n;i++){
m-=ener[i].a;
if(m<0) jg=0;
m+=ener[i].b;
}
if(jg)printf("Yes\n");
else printf("No\n");
}
return 0;
}