NC53681「土」巨石滚滚 题解

魔法使帕秋莉

题目大意

作为恶魔之馆红魔馆的头脑,魔法使帕秋莉掌握了一种土属性魔法,她使用这种魔法建造了一个大型的土球,并让其一路向下去冲撞障碍。土球有一个稳定性x,如果x < 0,它会立刻散架。每冲撞一个障碍,土球会丧失 a i a_i ai的稳定性,冲撞之后,又会从障碍身上回馈 b i b_i bi的稳定性。帕秋莉想知道,如果合理的安排障碍的顺序,在保证土球不散架的情况下,是否可以将障碍全部撞毁呢?

输入描述

输入一个整数T,代表T组数据,每组数据中:
前一行两个整数n , m,表示障碍个数和土球的稳定性
接下来一行两个整数,分别表示障碍的 a i a_i ai b i b_i bi
输入数据满足 ∑ \sum n <= 500000, 1<=m<=100000,0<=a,b<=100000

输出描述

若可以,输出“Yes”(不含引号),否则输出“No”(不含引号)

样例输入

1
5 50
49 49
52 0
5 10
26 24
70 70

样例输出

No

思路

我们先考虑容易的。将障碍分为增加稳定性和减少稳定性的两类,我们一定愿意先冲撞增加土球稳定性的障碍,以提升稳定性到最大值来准备冲撞接下来所有减少稳定性的障碍。此为贪心第一步。

在增加土球稳定性的障碍中,我们一定愿意先冲撞 a i a_i ai小的障碍,这样我们才不会一冲就散架。而且这一过程我们土球稳定性一直在增加,需要顾虑的只有 a i a_i ai。反之,假设我们不去区分增稳和减稳两类土球,只考虑 a i a_i ai小的,那么如果我们撞了一个减稳的障碍,土球稳定性就会减小,后面再遇到 a i a_i ai大的障碍,就散架了。

按照现在我们考虑的模式,就算我们一冲就散架,也不会出现更优的贪法了,因为在增稳障碍中我们都无法冲过,就算我们去冲 a i a_i ai更小的降稳障碍,虽然一时冲过,但最后土球稳定性一定降低,再冲 a i a_i ai较大的增稳障碍更冲不过了。故这种贪法是最优的。此为贪心第二步。

然后我们考虑减稳的障碍如何去冲。由贪心的思想,设冲撞顺序(A,B)优于(B,A),冲撞该顺序中第一个障碍前土球的稳定性为 m 1 m_1 m1,冲撞第一个障碍后土球的稳定性为 m 2 m_2 m2。对于(A,B),有 m 2 = m 1 − a A + b A m_2=m_1-a_A+b_A m2=m1aA+bA,对于(B,A),有 m 2 = m 1 − a B + b B m_2=m_1-a_B+b_B m2=m1aB+bB,若能成功冲撞第二个障碍,则分别需要满足 m 1 − a A + b A ≥ a B m_1-a_A+b_A≥a_B m1aA+bAaB m 1 − a B + b B ≥ a A m_1-a_B+b_B≥a_A m1aB+bBaA,即 m 1 ≥ a A + a B − b A m_1≥a_A+a_B-b_A m1aA+aBbA m 1 ≥ a A + a B − b B m_1≥a_A+a_B-b_B m1aA+aBbB,显然 m 1 m_1 m1需要达到的最小值越小,对冲撞成功就越有利,因此 b A > b B b_A>b_B bA>bB,即得到按照回复稳定性从大到小的顺序进行冲撞。此为贪心第三步。

考点

贪心

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=5e5+5;
struct Node{
    int a,b;
}node[maxn],node_win[maxn],node_lose[maxn];
bool cmp_win(const Node &A, const Node &B){
    return A.a<B.a;
}
bool cmp_lose(const Node &A, const Node &B){
    return A.b>B.b;
}
signed main(){
    int T,n,m;
    cin>>T;
    while(T--){
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>node[i].a>>node[i].b;
        int p=0,q=0,f=0;
        for(int i=1;i<=n;i++){
            if(node[i].a<=node[i].b)node_win[++p]=node[i];
            else node_lose[++q]=node[i];
        }
        sort(node_win+1,node_win+1+p,cmp_win);
        for(int i=1;i<=p;i++){
            if(node_win[i].a>m){
                f=1;break;
            }
            m-=node_win[i].a,m+=node_win[i].b;
        }
        sort(node_lose+1,node_lose+1+q,cmp_lose);
        for(int i=1;i<=q;i++){
            if(node_lose[i].a>m){
                f=1;break;
            }
            m-=node_lose[i].a,m+=node_lose[i].b;
        }
        f?puts("No"):puts("Yes");
    }
    return 0;
}

心得

这是一道究极贪心的题目,一共贪了三次心,是一道兼具定性的贪心思想和定量的贪心思想的题目,是非常值得深入理解的。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

keguaiguai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值