\(\mathcal{Description}\)
\(n\)个物品有长和宽,\(m\)个盒子也有长和宽,一个盒子最多可以装一个物品,问\(n\)个物品能否都放进盒子,物品和盒子不能旋转
\(\mathcal{Solution}\)
先离散化长和宽,将物品和盒子按照长从大到小排序
考虑到当前物品时将所有长大于等于当前物品的盒子全部放进一个权值线段树,权值线段树维护长大于等于当前物品的并且宽为\(x\)的盒子有多少个,则在线段树上二分出宽刚好大于x的位置,将对应数量减\(1\)即可
我是傻子,用multiset不需要离散化还自带二分和删除,就当是线段树二分练手吧
\(\mathcal{Code}\)
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 10;
const int maxt = 2e6 + 10;
struct pt {
int x, y;
}a[maxn], b[maxn];
int n, m, tot, rt;
int t[maxn << 1];
int val[maxt], ls[maxt], rs[maxt];
void insert (int &k, int l, int r, int x)
{
if (!k) k = ++tot;
if (l == r) return ++val[k], void();
int md = (l + r) >> 1;
if (x <= md) insert(ls[k], l, md, x);
else insert(rs[k], md + 1, r, x);
val[k] = val[ls[k]] + val[rs[k]];
}
bool delet (int &k, int l, int r, int x)
{
if (!k || !val[k]) return false;
if (l == r) return --val[k], true;
int md = (l + r) >> 1;
if (md >= x) {
if (!delet(ls[k], l, md, x)) return delet(rs[k], md + 1, r, x);
return true;
}
return delet(rs[k], md + 1, r, x);
}
bool cmp (pt x, pt y)
{
return x.x > y.x;
}
bool check ()
{
sort(a + 1, a + n + 1, cmp);
sort(b + 1, b + m + 1, cmp);
int i = 1, j = 1;
while (i <= n) {
while (j <= m && b[j].x >= a[i].x) insert(rt, 1, n + m, b[j].y), ++j;
if (!delet(rt, 1, n + m, a[i].y)) return false;
++i;
}
return true;
}
void lsh ()
{
int cnt = 0;
for (int i = 1; i <= n; ++i) t[++cnt] = a[i].x;
for (int i = 1; i <= m; ++i) t[++cnt] = b[i].x;
sort(t + 1, t + cnt + 1);
cnt = unique(t + 1, t + cnt + 1) - t - 1;
for (int i = 1; i <= n; ++i) a[i].x = lower_bound(t + 1, t + cnt + 1, a[i].x) - t;
for (int i = 1; i <= m; ++i) b[i].x = lower_bound(t + 1, t + cnt + 1, b[i].x) - t;
cnt = 0;
for (int i = 1; i <= n; ++i) t[++cnt] = a[i].y;
for (int i = 1; i <= m; ++i) t[++cnt] = b[i].y;
sort(t + 1, t + cnt + 1);
cnt = unique(t + 1, t + cnt + 1) - t - 1;
for (int i = 1; i <= n; ++i) a[i].y = lower_bound(t + 1, t + cnt + 1, a[i].y) - t;
for (int i = 1; i <= m; ++i) b[i].y = lower_bound(t + 1, t + cnt + 1, b[i].y) - t;
}
int main ()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i].x);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i].y);
for (int i = 1; i <= m; ++i) scanf("%d", &b[i].x);
for (int i = 1; i <= m; ++i) scanf("%d", &b[i].y);
lsh();
printf("%s\n", check() ? "Yes" : "No");
return 0;
}
标签:二分,return,int,线段,Wrapping,Chocolate,物品,盒子,ABC245E From: https://www.cnblogs.com/Morning-Glory/p/17617680.html如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧