官方的题解
注意到数据对象的大小都是2的整数次幂,贪心地把这些数据对象从大到小去往分条里存就是对的。一个做法是每次取剩下最大的数据对象,然后用堆来维护分条,每次取剩余空间最大的一个分条并将该数据对象存进去,如果存在存不进去的情况则无解,否则就有解。
时间复杂度:O(n log n +m log m)
类似于我们把n个物品装入m个箱子中,看是否能够装下,所以我们每次都是取最大的物品放入剩余空间最大的箱子中,如果物品全都装进入则输出“Yes”,否则输出“No”。
这里我们用优先队列来实现,完整代码如下:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 1e5+10;
bool cmp(int x,int y){
return x > y;
}
void solve(){
int a[maxn],b[maxn];
priority_queue<int>A,B;
int n,m;
long long sum1 = 0;
long long sum2 = 0;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
sum1 += a[i];//物品的体积
A.push(a[i]);
}
for(int i=0;i<m;i++){
scanf("%d",&b[i]);
sum2 += b[i];//箱子的容积
B.push(b[i]);
}
if(sum1>sum2){//物品的体积大于箱子的总容积
printf("No\n");
return ;
}
else{
while(!A.empty() && !B.empty()){
int x = A.top();
int y = B.top();
if(x>y){//当前物品装不下,说明输出“No”
break;
}
else{
y -= x;
sum1 -= x;
A.pop();
B.pop();
if(y) B.push(y);
}
}
if(sum1){
printf("No\n");
}
else printf("Yes\n");
}
}
int main(){
int t;
cin >> t;
while(t--){
solve();
}
return 0;
}