题意

  • 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;
}