当前位置: 首页 > news >正文

UVa 10587 Mayor‘s Posters

题目描述

Bytetown\texttt{Bytetown}Bytetown 的市长选举中,候选人们随意在墙上张贴海报,引起了市民的不满。市议会决定建造一面专门的选举墙,并制定以下规则:

  • 每位候选人只能在墙上贴一张海报
  • 所有海报高度与墙相同,宽度可以是任意整数字节(byte\texttt{byte}byteBytetown\texttt{Bytetown}Bytetown 的长度单位)
  • 墙被分成若干段,每段宽 111 字节
  • 每张海报必须完全覆盖一段连续的墙段

墙的总长度为 100000001000000010000000 字节。当竞选活动重新开始时,候选人们按顺序在墙上张贴海报,这些海报的宽度差异很大,而且后来的海报会覆盖之前海报的部分区域。

你的任务是找出在所有海报都张贴完毕后,有多少张海报仍然可见(即使只看到一部分也算可见)。

输入格式

第一行包含一个整数 ccc,表示测试用例的数量。
每个测试用例的第一行包含一个整数 nnn (1≤n≤100001 \leq n \leq 100001n10000),表示海报的数量。
接下来的 nnn 行按张贴顺序描述海报,每行包含两个整数 lil_ilirir_iri,表示第 iii 张海报覆盖的墙段范围(从 lil_ilirir_iri,包含端点)。

输出格式

对于每个测试用例,输出在所有海报都张贴完毕后,仍然可见的海报数量。

题目分析

问题核心

这是一个典型的区间覆盖问题,需要处理以下关键点:

  1. 覆盖顺序:后张贴的海报会覆盖之前海报的对应部分
  2. 大规模数据:墙的长度达到 10710^7107,但海报数量最多只有 100001000010000
  3. 可见性判断:海报只要有一部分未被覆盖就算可见

解题思路

逆向处理

采用从后往前的处理顺序:

  • 最后一张海报肯定完全可见
  • 倒数第二张海报只有未被之后海报覆盖的部分才可见
  • 依此类推…

这样我们只需要维护一个数据结构来记录当前哪些墙段已经被后续海报覆盖。

离散化优化

由于墙的长度很大 (10710^7107) 但实际用到的端点很少(最多 200002000020000 个),可以使用离散化技术:

  • 收集所有海报的端点坐标
  • 排序并去重
  • 建立原始坐标到紧凑索引的映射

这样就将坐标范围从 [1,107][1, 10^7][1,107] 压缩到 [1,20000][1, 20000][1,20000] 左右。

线段树维护

使用线段树配合懒标记来高效处理区间查询和更新:

  • 查询:判断当前海报区间内是否还有未被覆盖的段
  • 更新:将当前海报覆盖的区间标记为已覆盖

算法步骤

  1. 读取所有海报的区间信息
  2. 收集所有端点坐标,排序去重进行离散化
  3. 建立原始坐标到离散化索引的映射
  4. 从最后一张海报到第一张海报依次处理:
    • 将当前海报区间映射到离散化坐标
    • 查询该区间是否还有未被覆盖的部分
    • 如果有,则这张海报可见,计数器加 111
    • 将该区间标记为已覆盖
  5. 输出可见海报数量

复杂度分析

  • 离散化O(nlog⁡n)O(n \log n)O(nlogn)
  • 线段树操作:每次查询和更新都是 O(log⁡m)O(\log m)O(logm),其中 mmm 是离散化后的坐标数量
  • 总复杂度O(nlog⁡n+nlog⁡m)O(n \log n + n \log m)O(nlogn+nlogm),完全适合 n≤10000n \leq 10000n10000 的数据规模

代码实现

// Mayor's Posters
// UVa ID: 10587
// Verdict: Accepted
// Submission Date: 2025-10-21
// UVa Run Time: 0.020s
//
// 版权所有(C)2025,邱秋。metaphysis # yeah dot net#include <bits/stdc++.h>using namespace std;const int MAXN = 10000; // 最大海报数量struct Poster {int l, r; // 海报覆盖的左右端点
} posters[MAXN + 5];vector<int> vals; // 存储所有端点坐标用于离散化
unordered_map<int, int> mapping; // 原始坐标到离散化索引的映射// 线段树相关
const int MAXM = 20000; // 离散化后的最大坐标数量
bool tree[4 * MAXM]; // 线段树,记录区间是否完全被覆盖
bool lazy[4 * MAXM]; // 懒标记,表示该区间需要被覆盖// 下推懒标记
void push_down(int idx) {if (lazy[idx]) {tree[idx * 2] = true;tree[idx * 2 + 1] = true;lazy[idx * 2] = true;lazy[idx * 2 + 1] = true;lazy[idx] = false;}
}// 查询区间 [ql, qr] 是否全部被覆盖
bool query(int idx, int l, int r, int ql, int qr) {if (ql > r || qr < l) return true; // 无交集,视为已覆盖if (tree[idx]) return true; // 整个区间已被覆盖if (ql <= l && r <= qr) {return tree[idx]; // 当前区间完全在查询范围内}push_down(idx); // 下推懒标记int mid = (l + r) / 2;bool left_covered = true, right_covered = true;if (ql <= mid)left_covered = query(idx * 2, l, mid, ql, qr);if (qr > mid)right_covered = query(idx * 2 + 1, mid + 1, r, ql, qr);return left_covered && right_covered; // 左右子树都覆盖才算完全覆盖
}// 更新区间 [ql, qr] 为已覆盖
void update(int idx, int l, int r, int ql, int qr) {if (ql > r || qr < l) return; // 无交集,直接返回if (ql <= l && r <= qr) {tree[idx] = true; // 当前区间完全在更新范围内lazy[idx] = true; // 设置懒标记return;}push_down(idx); // 下推懒标记int mid = (l + r) / 2;if (ql <= mid)update(idx * 2, l, mid, ql, qr);if (qr > mid)update(idx * 2 + 1, mid + 1, r, ql, qr);tree[idx] = tree[idx * 2] && tree[idx * 2 + 1]; // 更新父节点
}int main() {ios::sync_with_stdio(false);cin.tie(0);int c;cin >> c; // 测试用例数量while (c--) {int n;cin >> n; // 海报数量vals.clear();mapping.clear();// 读取所有海报区间for (int i = 0; i < n; i++) {cin >> posters[i].l >> posters[i].r;vals.push_back(posters[i].l);vals.push_back(posters[i].r);}// 离散化处理sort(vals.begin(), vals.end());vals.erase(unique(vals.begin(), vals.end()), vals.end());int m = vals.size(); // 离散化后的坐标数量// 建立映射关系for (int i = 0; i < m; i++) {mapping[vals[i]] = i + 1; // 索引从1开始}// 初始化线段树memset(tree, 0, sizeof(tree));memset(lazy, 0, sizeof(lazy));int visible = 0; // 可见海报计数器// 从后往前处理海报for (int i = n - 1; i >= 0; i--) {int l = mapping[posters[i].l]; // 映射左端点int r = mapping[posters[i].r]; // 映射右端点// 查询当前海报区间是否还有未被覆盖的部分if (!query(1, 1, m, l, r)) {visible++; // 有未被覆盖的部分,该海报可见}// 更新线段树,标记该区间为已覆盖update(1, 1, m, l, r);}cout << visible << "\n";}return 0;
}

总结

本题通过逆向处理离散化线段树的巧妙结合,高效地解决了大规模区间覆盖的可见性问题。逆向处理保证了我们只需要关心后续海报的覆盖情况,离散化将问题规模从 10710^7107 压缩到 2×1042 \times 10^42×104 级别,线段树则提供了高效的区间查询和更新操作。这种组合思路在处理大规模区间问题时非常实用。

http://www.dtcms.com/a/513097.html

相关文章:

  • 非洲用什么网站做采购开源低代码平台
  • 网站服务器空间不足最好的建站平台
  • LeetCode 3143.正方形中的最多点数
  • python 做电商网站北京朝阳客户端
  • 错误示例和如何规避
  • 电子商务网站建设实训心得体会哪里做外贸网站
  • OPARTMENT发布Light 系列 以“光”重塑都市青年生活方式
  • Ubuntu 系统安装教程(二):系统安装
  • JVM调优实战:一次GC风暴的排查与优化全记录
  • 修改查询默认1W限制
  • 网站建设 宣传商丘网站建设有哪些
  • 商业网站的创建程序线上运营推广是做什么的
  • 泉港区建设局网站廉政网站建设调查的问卷
  • 常宁市城市建设规划管理局网站4a广告公司排名
  • CHI-Read Transaction
  • LeetCode——二分(进阶)
  • 便宜购 网站建设鹤岗商城网站建设
  • Vue图片压缩方案
  • python去掉不是ts文件的链接
  • 性病医院网站优化服务商中国品牌网站设计
  • win2008网站404成都职业培训网络学院
  • 网站源码授权wordpress调用相关页面
  • Excel 宏安全设置与强制启用宏
  • 万柳网站建设html网站开发中的应用
  • 中国站长小程序源码能直接用吗
  • 《通信之道—从微积分到5G》阅读笔记
  • 郑州网站建设网页设计网站备案转入
  • 广州网站建设出售sae wordpress 主题
  • 为什么在大数据处理场景下,存储过程比编程语言更合适?
  • 电子商务网站建设与管理课件辽宁建设工程信息网备案