1 条题解

  • 0
    @ 2025-10-24 11:19:15

    题意分析

    我们有 nn 个巧克力,每个巧克力是二维平面上的点 (x,y)(x, y),带权值 hh

    mm 个询问,每个询问给出 (a,b,c)(a, b, c),要求计算所有满足 [ a x + b y < c ] 的巧克力的 hh 值之和。


    核心难点

    • n,m50000n, m \le 50000,需要高效查询。
    • a,b,x,ya, b, x, y 范围很大([109,109][-10^9, 10^9]),且可为负数。
    • 查询是半平面形式 ax+by<ca x + b y < c,但 a,ba, b 符号不确定,所以方向任意。

    解法思路

    1. 暴力法

    对每个询问,遍历所有巧克力,检查条件并累加 hh
    复杂度 O(nm)O(n m),不可行。


    2. 半平面查询问题

    查询 ax+by<ca x + b y < c 等价于点在直线 ax+by=ca x + b y = c 的某一侧。

    由于 a,ba, b 可正可负,这个半平面可能是任意方向的。

    对于这种任意方向半平面点权和查询,常用方法有:

    • K-D Tree 配合剪枝
    • 半平面扫描(但这里 mm 很大,难做)

    K-D Tree 解法

    K-D Tree 可以在 O(n)O(\sqrt{n}) 平均时间内完成矩形区域查询,但这里是半平面查询,需要特殊处理。


    关键观察

    我们可以将 ax+by<ca x + b y < c 看作线性函数 f(p)=ax+byf(p) = a x + b y 的值小于 cc

    在 K-D Tree 查询时,对每个节点维护其包围盒(xmin,xmax,ymin,ymaxx_{\min}, x_{\max}, y_{\min}, y_{\max}),并计算 f(p)f(p) 在包围盒上的最小值和最大值


    剪枝策略

    对于当前节点:

    1. 如果包围盒的 fmax<cf_{\max} < c,则整个节点内的点都满足条件,直接返回该子树权值和。
    2. 如果包围盒的 fmincf_{\min} \ge c,则整个节点内的点都不满足条件,直接返回 00
    3. 否则递归查询左右子树。

    复杂度

    • 建树:O(nlogn)O(n \log n)
    • 单次查询:最坏 O(n)O(n),但随机数据下约 O(n)O(\sqrt{n}),且剪枝有效。
    • 总复杂度:O(mn)O(m \sqrt{n}),在 n,m=50000n,m=50000 时勉强可过(约 3.5×1073.5 \times 10^7 操作)。

    算法步骤

    1. 读入 n,mn, m 和巧克力数据 (x,y,h)(x, y, h)
    2. 构建 K-D Tree(按 x,yx, y 交替划分),每个节点维护:
      • 包围盒 [xmin,xmax]×[ymin,ymax][x_{\min}, x_{\max}] \times [y_{\min}, y_{\max}]
      • 子树 hh
    3. 对每个查询 (a,b,c)(a, b, c)
      • 在 K-D Tree 上做 DFS,用上述剪枝。
      • 对叶子节点直接检查 ax+by<ca x + b y < c
    4. 输出每个查询的结果。

    样例验证

    输入:

    3 3
    1 2 5
    3 1 4
    2 2 1
    2 1 6
    1 3 5
    1 3 7
    

    巧克力:

    • P1=(1,2),h=5P_1=(1,2), h=5
    • P2=(3,1),h=4P_2=(3,1), h=4
    • P3=(2,2),h=1P_3=(2,2), h=1

    查询 1: a=2,b=1,c=6a=2, b=1, c=6
    条件 2x+y<62x + y < 6

    • P1P_1: 2×1+2=4<62\times 1 + 2 = 4 < 6
    • P2P_2: 6+1=766 + 1 = 7 \ge 6
    • P3P_3: 4+2=664 + 2 = 6 \ge 6
      和 = 5,输出 5。

    查询 2: a=1,b=3,c=5a=1, b=3, c=5
    条件 x+3y<5x + 3y < 5

    • P1P_1: 1+6=751 + 6 = 7 \ge 5
    • P2P_2: 3+3=653 + 3 = 6 \ge 5
    • P3P_3: 2+6=852 + 6 = 8 \ge 5
      和 = 0,输出 0。

    查询 3: a=1,b=3,c=7a=1, b=3, c=7
    条件 x+3y<7x + 3y < 7

    • P1P_1: 777 \ge 7
    • P2P_2: 6<76 < 7
    • P3P_3: 878 \ge 7
      和 = 4,输出 4。

    与样例输出一致。


    优化技巧

    1. 轮换划分:K-D Tree 按 xxyy 轮换划分,保持平衡。
    2. 启发式选择划分点:选中位数作为划分点,使树平衡。
    3. 提前计算极值:对每个节点预计算 ax+bya x + b y 的最小最大值(在查询时根据 a,ba,b 计算,因为 a,ba,b 每次不同)。
      • 对包围盒 [xl,xr]×[yl,yr][x_l, x_r] \times [y_l, y_r]fmin=min(axl,axr)+min(byl,byr)f_{\min} = \min(a x_l, a x_r) + \min(b y_l, b y_r)(注意 a,ba,b 符号)
      • 同理 fmax=max(axl,axr)+max(byl,byr)f_{\max} = \max(a x_l, a x_r) + \max(b y_l, b y_r)

    总结

    这道题通过 K-D Tree 的包围盒极值剪枝,将半平面查询转化为区域查询,利用 O(n)O(\sqrt{n}) 的平均复杂度处理大规模数据,是 K-D Tree 在半平面查询中的典型应用。

    • 1

    信息

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