1 条题解
-
0
算法思路
本题要求找到一个固定大小 的矩形,使其覆盖的垃圾总重量最大。这是一个二维区间最大和问题。
核心算法
1. 问题转换
将二维问题转换为一维问题:
- 由于矩形宽度固定为 ,我们可以用滑动窗口在 x 轴方向移动
- 对于每个 x 区间 ,我们需要找到在 y 轴方向高度为 的区间能获得的最大重量和
2. 算法框架
使用扫描线 + 线段树的解法:
- 按 x 坐标排序所有点
- 用双指针维护 x 方向在 范围内的点
- 用线段树维护 y 轴方向的高度区间和
3. 关键步骤
坐标离散化
sort(bx + 1, bx + n + 1), sort(by + 1, by + n + 1); int lenx = unique(bx + 1, bx + n + 1) - bx - 1; int leny = unique(by + 1, by + n + 1) - by - 1;将 范围的坐标映射到 范围内,便于处理。
滑动窗口维护
for (int i = 1; i <= mxx; i++) { // 移除超出左边界的点 for (int j = del + 1; j <= n; j++) { if (vx[i] - vx[t[j].x] + 1 > W) { // 从线段树中删除该点的影响 modify(1, l, r, -t[j].w); } else { del = j - 1; break; } } // 添加当前x坐标的点 for (int j : point[i]) { modify(1, l, r, t[j].w); } ans = max(ans, tree[1].mx); }线段树操作
线段树用于维护每个 y 坐标区间 内的重量和:
modify(): 区间加操作,添加或删除点的影响tree[1].mx: 根节点存储当前最大区间和
算法标签
- 扫描线算法 (Sweep Line)
- 线段树 (Segment Tree)
- 坐标离散化 (Coordinate Compression)
- 滑动窗口 (Sliding Window)
- 双指针技巧 (Two Pointers)
复杂度分析
- 时间复杂度:
- 排序和离散化:
- 线段树操作: 每个点最多被加入和删除一次,每次
- 空间复杂度:
代码关键点解析
-
离散化处理:
int nowx = lower_bound(bx + 1, bx + lenx + 1, t[i].x) - bx; int nowy = lower_bound(by + 1, by + leny + 1, t[i].y) - by;将大范围坐标映射到小范围索引
-
y区间计算:
int l = lower_bound(by + 1, by + leny + 1, vy[t[j].y] - H + 1) - by; int r = lower_bound(by + 1, by + leny + 1, vy[t[j].y]) - by;计算点 影响的高度区间
-
懒标记线段树:
- 支持区间加操作
- 支持区间最大值查询
- 懒标记优化保证复杂度
样例验证
对于样例输入:
5 3 2 3 1 10 2 1 5 1 0 5 0 2 10 1 3 5算法过程:
- 按 x 排序点:x=0,1,1,2,3
- 滑动窗口扫描:
- 当窗口覆盖 x∈[1,3] 时
- 包含点:(1,0,5), (2,1,5), (3,1,10)
- 总重量 = 5+5+10 = 20(最大值)
该解法通过巧妙的坐标离散化和线段树维护,高效解决了二维区间最大和问题,能够处理 规模的数据。
- 1
信息
- ID
- 4017
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者