链接:https://ac.nowcoder.com/acm/contest/2272/H
来源:牛客网
帕秋莉掌握了一种土属性魔法
她使用这种魔法建造了一个大型的土球,并让其一路向下去冲撞障碍
土球有一个稳定性x,如果x < 0,它会立刻散架
每冲撞一个障碍,土球会丧失ai的稳定性,冲撞之后,又会从障碍身上回馈bi的稳定性
帕秋莉想知道,如果合理的安排障碍的顺序,在保证土球不散架的情况下,是否可以将障碍全部撞毁呢?
输入描述:
输入一个整数T,代表T组数据,每组数据中:
前一行两个整数n , m,表示障碍个数和土球的稳定性
接下来一行两个整数,分别表示障碍的ai和bi
输出描述:
若可以,输出“Yes”(不含引号),否则输出“No”(不含引号)
示例1
输入
复制
1
5 50
49 49
52 0
5 10
26 24
70 70
输出
复制
No
备注:
Σn <= 500000, 1<=m<=100000,0<=a,b<=100000
这题还是比较简单的,只是选择何种数据结构来操作。我们知道如果当前的障碍物能够回馈我们更多的稳定性,那么我们选择优先撞它。意思是我们将bi>=ai的放在一起,按照ai,从小到大排序。然后将ai>bi的放在一起,按照ai从大到小排序,如果当前的m小于ai,我们就可以退出了,可以减小一些时间复杂度。
vector容器可以装任意类型的元素,包括结点。然后重载一下排序,然后auto自动类型。记得每一次将vector内容清空。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5+5;
struct node{
ll a,b;
};
vector<node>adds,subs;
ll n,m;
int cmp1(node a,node b)
{
return a.a<b.a;
}
int cmp2(node a,node b)
{
return a.b>b.b;
}
int main()
{
int tt ;
scanf("%d",&tt);
while(tt--)
{
adds.clear();
subs.clear();
scanf("%lld %lld",&n,&m);
for(int i=1; i<=n; i++)
{
ll a,b; scanf("%lld %lld",&a,&b);
if( b>=a ) adds.push_back( {a,b} );
else subs.push_back( {a,b} );
}
sort(adds.begin(),adds.end(),cmp1);
int flag = 1;
// 1.首先先撞 a<=b 的障碍物: 先撞a小的,直接模拟
for( auto i:adds )
{
if( i.a>m ) // 立刻散架
{
flag = 0;
break;
}
else m += (i.b-i.a);
}
if( flag==0 )
{
puts("No");
}
else
{
/*
2.然后在撞 a>b
不管最终排序如何,最终的m值是确定的(如果能完成全部冲撞)。
倒序来看,即分析逆过程。之前每次冲撞先消耗a,再恢复b,
逆过程为先增加b后消耗a,所以逆推应当按照b升序排列,
那么正推就该是按b降序排列。
*/
sort(subs.begin(),subs.end(),cmp2);
for( auto i:subs )
{
if( i.a>m ) // 立刻散架
{
flag = 0;
break;
}
else m += (i.b-i.a);
}
puts(flag?"Yes":"No");
}
}
return 0;
}