题解:AT_abc245_e [ABC245E] Wrapping Chocolate

我绝对不会告诉你我打比赛时没做出来这道题。

题目简化:给定每个巧克力和盒子的长宽,已知每个盒子只能放一块巧克力,并且必须保证巧克力能放下,求是否所有巧克力都能放入。

思路:贪心、二分、排序、STL。

首先看到这道题,最容易想到的算法就是暴力枚举。当然这是不可能的。所以时间复杂度只能是 O(nlog⁡2(n))O(n\log_2(n))O(nlog2(n))O(n)O(n)O(n) 的。

O(n)O(n)O(n) 的我是没想出来,但我一看到 log⁡2(n)\log_2(n)log2(n),瞬间就想到了两个东西:二分和排序。因为二分就需要排序,所以这里肯定两种都用了。

那排序我们只能排序一个量,但题目中有长宽两个变量,我们怎么排序呢?这时,我们就需要 OI 中一个很重要的思想:化二维为一维。

我们可以这么干:首先按照长排序(具体怎么排大家自己想),然后对于每一个巧克力的宽,我们在盒子中找到能包含它的,全部推入一个数组中,接着对这个数组二分找第一个能容下它的。这一步是贪心,想必大家都能想明白。

最后,如果没有能容下这块巧克力的盒子,直接输出 No 就对了。如果能装下,只需要把这个盒子弹出就行了。(这里就需要思考如何排序了。)

问题:二分需要排序,而快排是 O(nlog⁡2(n))O(n\log_2(n))O(nlog2(n)) 的,这样一循环不就超时了吗?很简单,只需要用 multiset 就好了,它的排序是 O(log⁡2(n))O(\log_2(n))O(log2(n)) 级别的。

AC 代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct wc {
	int x,y;
} a[200006],b[200006];
int n,m;
inline bool cmp(wc x,wc y) {
	return x.x>y.x;
}
inline bool cmp1(wc x,wc y) {
	return x.x<y.x;
}
signed main() {
	cin>>n>>m;
	for(int i=1; i<=n; i++) {
		cin>>a[i].x;
	}
	for(int i=1; i<=n; i++) {
		cin>>a[i].y;
	}
	for(int i=1; i<=m; i++) {
		cin>>b[i].x;
	}
	for(int i=1; i<=m; i++) {
		cin>>b[i].y;
	}
	sort(a+1,a+n+1,cmp);//具体原因自己想
	sort(b+1,b+m+1,cmp1);
	multiset<int>ms;
	int j=m;
	for(int i=1; i<=n; i++) {
		for(; b[j].x>=a[i].x&&j>=1; j--) {
			ms.insert(b[j].y);
		}
		auto it=ms.lower_bound(a[i].y);
		if(it==ms.end()) {
			cout<<"No";
			return 0;
		}
		ms.erase(it);//弹出盒子
	}
	cout<<"Yes";
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值