1 条题解

  • 0
    @ 2025-10-19 15:56:04

    题意

    有两个数组 aa(长度 nn)和 bb(长度 mm),问 aa 有多少个长度为 mm 的连续子数组能与 bb 匹配。
    匹配的定义:两个数组的数可以一一配对,每对 (ai,bj)(a_i, b_j) 满足 ai+bjha_i + b_j \ge h


    核心思路

    这是一个贪心匹配问题。
    最优的匹配方法是:
    bb 从小到大排序,将 aa 的子数组也从小到大排序,然后最小配最小,次小配次小,……,如果每一对都满足 ai+biha_i + b_i \ge h,则匹配成功。


    快速判断

    我们不需要真的排序每个子数组并检查,这样太慢(O(nmlogm)O(n m \log m))。
    可以这样优化:

    1. bb 排序。
    2. 对于 aa 的某个子数组,我们想知道:排序后是否满足 a[i]+b[i]ha'[i] + b[i] \ge h 对所有 ii 成立。
    3. 等价于:对于每个 b[i]b[i],在子数组中至少有 i+1i+1 个数 hb[i]\ge h - b[i](因为排序后第 ii 小的 aa' 必须 hb[i]\ge h - b[i])。

    转换问题

    定义 c[i]=hb[i]c[i] = h - b[i](注意 bb 已排序,所以 cc 是降序的)。
    条件变为:子数组中 c[i]\ge c[i] 的数的个数 i+1\ge i+1(对 i=0m1i=0 \dots m-1)。


    进一步简化

    其实只需要检查:对于每个 ii,子数组中 c[i]\ge c[i] 的数的个数 i+1\ge i+1
    ii 增大时 c[i]c[i] 减小,条件自动满足吗?
    不,因为 ii 增大时要求个数更多,但 c[i]c[i] 减小,所以可能更容易满足。
    实际上,只需要检查最严格的条件:
    对于每个 kk1km1 \le k \le m),子数组中 c[mk]\ge c[m-k] 的数的个数 k\ge k


    实现方法

    • bb 排序,计算 c[i]=hb[m1i]c[i] = h - b[m-1-i](反转一下,让 cc 升序)。
    • 这样条件变成:子数组中 c[k]\ge c[k] 的数的个数 k\ge kk=1mk=1 \dots m)。
    • 用线段树或 Fenwick 树维护 aa 中每个值出现的次数,滑动窗口时更新。
    • 对每个 kk,检查当前窗口 c[k]\ge c[k] 的数量是否 k\ge k,如果所有 kk 都满足,则答案加一。

    复杂度

    排序 O(mlogm)O(m \log m),滑动窗口 O(n)O(n),每次检查 mm 个条件,直接做是 O(nm)O(n m),但可以优化到 O(nlogm)O(n \log m) 用二分或树维护。


    最终答案就是满足条件的子数组个数。

    • 1

    信息

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