ABC 245 | E - Wrapping Chocolate
题目描述
给定\(N\)个矩形巧克力,第\(i\)块宽为\(A_i\),长为\(B_i\);
给定\(M\)个盒子,第\(i\)个盒子宽为\(C_i\),长为\(D_i\);
每个盒子只能放一块巧克力,且只有当满足\(A_i \le C_j\)且\(B_i \le D_j\),巧克力才能放入盒子;
问能否将所有巧克力都放入盒子中?
数据范围
- \(1 \le N \le M \le 2 \times 10^5\)
- \(1 \le A_i, B_i, C_i, D_i \le 10^9\)
解题思路
首先按照以下原则降序排序:
- 首先按照宽进行降序排序
- 若宽相等,按照长进行降序排序
- 若长与宽均相等,先排盒子,后排巧克力
代码如下:
struct Object{
int w, l, t;
bool operator < (const Object &p)const
{
if(w == p.w && l == p.l) return t > p.t;
if(w == p.w) return l > p.l;
return w > p.w;
}
} a[N];
排序后从左到右进行遍历:
- 若为盒子,则将长加入
multiset - 若为巧克力,则在
multiset中查找\(\ge\)巧克力长的数字,若有,则继续查找;若无,则输出No
代码如下:
for(int i = 0; i < n + m; i ++){
if(a[i].t == 1) ss.insert(a[i].l);
else if(a[i].t == 0){
auto x = ss.lower_bound(a[i].l); //返回的是指向该位置的迭代器
if(x == ss.end()){ //可以直接比较,不打*
puts("No");
return 0;
}
else ss.erase(x); //删除对应地址的一个元素
}
}
puts("Yes");
该题要求我们找出一个合理的排序顺序,思维难点在于将巧克力与盒子混合排序,然后用multiset在\(O((M + N) \log{(M + N)})\)时间复杂度内得到答案。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int N = 4e5 + 10;
int n, m;
multiset<int> ss;
struct Object{
int w, l, t;
bool operator < (const Object &p)const
{
if(w == p.w && l == p.l) return t > p.t;
if(w == p.w) return l > p.l;
return w > p.w;
}
} a[N];
int main()
{
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i ++) scanf("%d", &a[i].w), a[i].t = 0;
for(int i = 0; i < n; i ++) scanf("%d", &a[i].l);
for(int i = 0; i < m; i ++) scanf("%d", &a[i + n].w), a[i + n].t = 1;
for(int i = 0; i < m; i ++) scanf("%d", &a[i + n].l);
sort(a, a + n + m);
for(int i = 0; i < n + m; i ++){
if(a[i].t == 1) ss.insert(a[i].l);
else if(a[i].t == 0){
auto x = ss.lower_bound(a[i].l);
if(x == ss.end()){
puts("No");
return 0;
}
else ss.erase(x);
}
}
puts("Yes");
return 0;
}

浙公网安备 33010602011771号