1 条题解

  • 0
    @ 2026-6-19 10:30:37

    📝 题目大意

    NN 个产品,每个产品有价格 PiP_i 和若干功能。定义产品 ii "绝对优越"于产品 jjPiPjP_i \ge P_j,且 ii 的所有功能 jj 都具备,且 Pi>PjP_i > P_jjj 有至少一个功能是 ii 没有的。判断是否存在这样一对产品。

    💡 解题思路

    1. 题目分析N,M100N, M \le 100,数据范围很小,可以直接 O(N2)O(N^2) 暴力枚举所有产品对进行判断。题目中功能编号已按升序给出,方便后续做子集判断。

    2. 算法推导

      • 将每个产品的功能列表排序(虽然题目保证已有序,但排序保证安全)。
      • 将所有产品按价格从小到大排序(cmp 函数按 p 升序)。这样枚举时,对于 i>ji > j 总有 a[i].pa[j].pa[i].p \ge a[j].p,自动满足条件一。
      • 双重循环枚举 jj(较便宜)和 ii(较贵,i>ji > j),用双指针判断 a[i]a[i] 的功能是否全部包含在 a[j]a[j] 中:
        • k 指向 a[i]a[i] 的当前功能,遍历 a[j]a[j] 的每个功能,若匹配则 k++
        • k > a[i].c(即 a[i]a[i] 的全部功能都在 a[j]a[j] 中找到),则 bk=1,表示条件二成立。
      • bk=1,再检查条件三:a[i].p > a[j].p(严格更贵)或 a[j].c > a[i].cjj 的功能数多于 ii,由于条件二已保证 ii 的功能 \subseteq jj 的功能,功能数更多意味着 jj 必然有 ii 没有的功能)。
      • 任一条件满足即输出 Yes 并结束;全部枚举完未找到则输出 No
    3. 边界与细节

      • 条件三中"jj 有至少一个功能 ii 没有"在条件二(ii 的功能 \subseteq jj 的功能)的前提下,等价于 a[j].c>a[i].ca[j].c > a[i].c(功能数量更多)。若数量相等,则两产品功能完全相同,此时只能靠 Pi>PjP_i > P_j 来满足条件三。
      • 排序后 i > j 保证 PiPjP_i \ge P_j,但注意条件三要求 Pi>PjP_i > P_j(严格大于),因此价格相等时必须依赖功能数差异。
      • 双指针判断子集时,两个功能列表都需事先排序。

    ⏱️ 复杂度分析

    • 时间复杂度O(N2M)O(N^2 \cdot M)。枚举 O(N2)O(N^2) 对产品,双指针比较 O(Ci+Cj)=O(M)O(C_i + C_j) = O(M)
    • 空间复杂度O(NM)O(N \cdot M),用于存储所有产品的功能列表。

    💻 标准代码 (C++)

    #include<bits/stdc++.h>
    using namespace std;
    
    // 产品结构体:价格 p、功能数 c、功能列表 f
    struct nd{int p, c, f[110];}a[110];
    
    // 按价格从小到大排序,方便后续枚举
    bool cmp(nd n1, nd n2){return n1.p < n2.p;}
    
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d%d", &a[i].p, &a[i].c);
            for(int j = 1; j <= a[i].c; j++)
                scanf("%d", &a[i].f[j]);
            // 对每个产品的功能排序,保证双指针判断子集正确
            sort(a[i].f + 1, a[i].f + a[i].c + 1);
        }
        // 按价格升序排列所有产品
        sort(a + 1, a + n + 1, cmp);
    
        // 枚举 j(较便宜)和 i(较贵)
        for(int j = 1; j < n; j++)
            for(int i = j + 1; i <= n; i++)
            {
                int k = 1;               // 双指针:指向 a[i] 的当前功能
                bool bk = 0;             // 标记 a[i] 的功能是否全是 a[j] 的子集
                for(int t = 1; t <= a[j].c; t++)
                {
                    if(a[j].f[t] == a[i].f[k])  // 匹配到 a[i] 的一个功能
                        k++;
                    if(k > a[i].c)              // a[i] 的全部功能都已在 a[j] 中找到
                    {
                        bk = 1;
                        break;
                    }
                }
                if(bk == 0) continue;  // 条件二不满足,跳过
    
                // 条件三:更贵(P_i > P_j) 或 更多功能(a[j].c > a[i].c)
                if(a[i].p > a[j].p || a[j].c > a[i].c)
                {
                    puts("Yes");
                    return 0;
                }
            }
        puts("No");
        return 0;
    }
    
    • 1

    信息

    ID
    727
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    1
    已通过
    1
    上传者