• 【每日一题】补档 ABC309F - Box in Box | 三维偏序 | 树状数组 | 中等


    题目内容

    原题链接

    给定 n n n 个箱子,问是否存在一个箱子 x x x 是否可以放到另一个箱子 y y y 里。
    需要满足 h x < h y , w x < w y , d x < d y h_xhx<hy,wx<wy,dx<dy
    箱子可以随意翻转。

    数据范围

    1 ≤ n ≤ 2 ⋅ 1 0 5 1\leq n\leq 2\cdot 10^5 1n2105
    1 ≤ h i , w i , d i ≤ 1 0 9 1\leq h_i,w_i,d_i\leq 10^9 1hi,wi,di109

    题解

    首先按从小到大对 h , w , d h,w,d h,w,d 进行排序。

    这里假设对所有的箱子,排序后都有 h ≤ w ≤ d h\leq w\leq d hwd

    那么我们再按照 h h h 为第一关键字, w w w 为第二关键字, d d d 为第三关键字对箱子进行从小到大的排序。

    然后我们从按 h h h 从小到大枚举,每次将所有 h h h 相同的箱子一起枚举。

    这样,我们就可以对剩下的 w w w d d d 构建树状数组了。

    对于箱子 i i i ,找到 h j < h i h_jhj<hi j j j ,且 w j < w i w_jwj<wi 的最小的 d j d_j dj 。判断 d j < d i d_j < d_i dj<di 是否成立即可。

    然后在判断完后,将所有值为 h i h_i hi 的箱子都加入到树状数组中。

    q u e r y ( p ) query(p) query(p) 其实是在求 w ≤ p w\leq p wp 的最小的 d d d

    这个问题又叫三维偏序。

    时间复杂度: O ( n log ⁡ n ) O(n\log n) O(nlogn)

    代码

    #include 
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    
    struct Node {
        int a[3];
    };
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int n;
        cin >> n;
    
        vector<Node> vec(n);
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < 3; ++j) cin >> vec[i].a[j];
            sort(vec[i].a, vec[i].a + 3);
        }
    
        sort(vec.begin(), vec.end(), [](const Node& A, const Node& B) {
            return A.a[0] < B.a[0];
        });
    
        vector<int> b;
        for (int i = 0; i < n; ++i) b.push_back(vec[i].a[1]);
        sort(b.begin(), b.end());
        b.erase(unique(b.begin(), b.end()), b.end());
    
        auto get = [&](int x) {
            return int(lower_bound(b.begin(), b.end(), x) - b.begin() + 1);
        };
    
        for (int i = 0; i < n; ++i) vec[i].a[1] = get(vec[i].a[1]);
    
        int m = int(b.size());
        vector<int> tr(m + 1, INF);
    
        auto update = [&](int p, int x) {
            while (p <= m) {
                tr[p] = min(tr[p], x);
                p += (p & -p);
            }
        };
    
        auto query = [&](int p) {
            int res = INF;
            while (p >= 1) {
                res = min(res, tr[p]);
                p -= (p & -p);
            }
            return res;
        };
    
        bool ok = false;
        for (int i = 0; i < n; ++i) {
            int j = i + 1;
            while (j < n && vec[j].a[0] == vec[i].a[0]) j += 1;
    
            // 找到是否存在这么一个即可
            for (int k = i; k < j; ++k) {
                if (query(vec[k].a[1] - 1) < vec[k].a[2]) {
                    ok = true;
                    break;
                }
            }
            if (ok) break;
    
            // 把当前的部分全部添加进去
            for (int k = i; k < j; ++k) {
                update(vec[k].a[1], vec[k].a[2]);
            }
    
            i = j - 1;
        }
    
        if (ok) cout << "Yes\n";
        else cout << "No\n";
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
  • 相关阅读:
    Linux入门之使用 ps 查看系统进程
    蓝牙核心规范(V5.4)10.9-BLE 入门笔记之GAP
    全新UI简洁又不失美观的短视频去水印微信小程序源码,支持多做流量主模式
    集合框架(二)前置知识
    如果在 Mac 上的 Safari 浏览器中无法打开网站
    最近踩的两条sql的坑
    CSS中图片旋转超出父元素解决办法
    三坐标CMM尺寸公差质量SPC管理工具
    教你使用Jupyter可视化查询语句的语法树
    rust下载文件
  • 原文地址:https://blog.csdn.net/weixin_43900869/article/details/132768141