• Wrapping Chocolate(multiset、贪心)


    题意

    给定\(n\)个巧克力,对于第\(i\)个巧克力,其宽是\(A_i\),长是\(B_i\)
    给定\(m\)个盒子,对于第\(i\)个盒子,其宽是\(C_i\),长是\(D_i\)
    若第\(i\)个巧克力能被第\(j\)个盒子装下,需要满足\(A_i \leq C_j\),并且\(B_i \leq D_j\)
    每个盒子最多只能装一个巧克力。
    问所有巧克力是否都能被装下?

    数据范围

    \(1 \leq n \leq m \leq 2 \times 10^5\)

    思路

    首先这个题目一个初步的想法就是,巧克力和盒子都先按照宽从小到大排序。然后利用双指针,\(i\)表示当前扫描到的巧克力,\(j\)表示宽满足要求的第一个盒子(下标\(\geq j\)的盒子的宽也都是满足要求的)。
    但是此时,下标从\(j\)\(m\)的盒子的长是无序的,无法处理。那么,有没有什么方法可以自动排序呢,可以想到的是multiset。
    这样的话,还是不好维护,因为随着\(j\)向后移动,multiset会不知道该弹出哪个元素。
    那么,可以从大到小枚举,这样会将元素加入multiset中,而不是弹出。对于每个巧克力,找到multiset中满足要求的长中最小值,将其弹出即可。如果长的最大值也无法满足要求,那么当前的巧克力就不能被装下。

    这里官方题解给出的方法大致相同,但是思路更加清晰。
    将巧克力和盒子放在一起,按照宽从大到小排序,如果巧克力和盒子的宽相等,那么将盒子排在前面。
    扫描这个序列,同时维护一个multiset。如果当前扫描到的是盒子,那么就将其长加入multiset中;如果是巧克力,找到满足要求的长的最小值,并弹出。如果找不到,则不能被装下。
    注:multiset中维护的其实是宽满足要求的盒子的长。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    
    using namespace std;
    
    const int N = 400010;
    
    int n, m;
    
    struct Item
    {
        int w, l, type;
    
        bool operator < (const Item &t) const
        {
            if(w == t.w) return type < t.type;
            return w < t.w;
        }
    }a[N];
    
    multiset<int> b;
    
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i].w);
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i].l);
        for(int i = 1; i <= n; i ++) a[i].type = 1;
        for(int i = n + 1; i <= n + m; i ++) scanf("%d", &a[i].w);
        for(int i = n + 1; i <= n + m; i ++) scanf("%d", &a[i].l);
        for(int i = n + 1; i <= n + m; i ++) a[i].type = 2;
        sort(a + 1, a + n + m + 1);
        for(int i = n + m; i >= 1; i --) {
            auto t = a[i];
            if(t.type == 2) b.insert(t.l);
            else {
                int p = t.l;
                auto loc = b.lower_bound(p);
                if(loc == b.end()) {
                    printf("No\n");
                    return 0;
                }
                b.erase(loc);
            }
        }
        printf("Yes\n");
        return 0;
    }
    
  • 相关阅读:
    (译)linux系统关于命令echo的15个例子
    linux之grep实例讲解
    linux grep练习
    (译)"usermod"命令使用完全指导---15个练习例程截图
    linux分区,文件系统,目录结构概述
    Linux 配置YUM
    Linux 强制安装rpm 包
    $LANG、$NLS_LANG 记录一下
    Oracle性能诊断艺术-相关脚本说明
    datafile相关(add、rename、drop)
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16064652.html
Copyright © 2020-2023  润新知