线段树与离散化技巧 Mayors posters——poj 2528

news/2024/9/18 11:21:34/文章来源:https://www.cnblogs.com/oQAQo/p/18409808

问题描述:
有一堵海报墙,从左到右一共有10000000个小块,墙上贴了许多海报,每张海报的高度与墙的高度相同,宽度不同,新帖的海报会将原有的海报覆盖,问当所有人把海报贴完是,墙上可以看到几张海报
输入:
第一行输入一个整数c表示测试数,每个测试第一行输入一个整数n(1<=N<=10000),代表张贴海报数量,之后的n行,每行输入两个整数,L,R,表示海报的左右位置,它覆盖的区间为L,R
输出:
对于每个测试,输出能看到的海报数量

题目分析:
如何才能判断一面墙上有几张海报,正常我们用肉眼判断肯定是找每一张的特征,先把不同的海报区分开来,然后一个一个数,如果在计算机中,那每张海报在记录时肯定要有标记,按照题目意思,该标记还要可以被部分覆盖,那么就简单了,我们可以将一张海报看成一个区间,在这个区间中只有一种标记代表这张海报,这种标记填满这个区间,那么就可以被部分覆盖,我们把每张海报编号,在及记录(张贴)该海报时把该编号写满该区间每个元素,(我们这里是指数组的值),那么之后记录的海报就可以对区间重新赋值,这些似乎都是区间操作,那么线段树肯定是首选,可以使用tag标记结合哈希表检索这个海报是否被覆盖,但该墙上有10000000个小块,就意味着我们需要创建一个N=10000000大小的数组,而线段树tree[4N],这个空间是巨大的,有没更省空间的方法,答案是有的,我们观察到,其实海报原有的宽度并不影响我们计算,完全可以改成任何一个合理的数,有这种特性的例子可以利用离散化的技巧,总共10000张海报那么最多就有20000个left和right,N=20000直接省下极大空间,但需要注意的是,离散化会将原本离散的数据变得紧凑,这是离散化的用途,但在本题中需要更改,比方说一个大区间L1,R1,这个大区间中只有两个小区间[L1,r],[l,R1],那么离散化之后r和l会被看作是连续的,会导致[r,l]的大区间部分被覆盖,实际上并没有, 那么最终结果只有两张海报,大区间[L1,R1],被误判为完全覆盖了,要避免这个问题只需要在离散化是在r和l之间在添加一个元素即可,下面直接看代码:

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 100014;
int n, m;
int lazy[MAXN << 2];
int num[MAXN << 2];
int left1[MAXN];
int right1[MAXN];
bool vis[MAXN];
int ans = 0;int ls(int id) { return id << 1; }
int rs(int id) { return id << 1 | 1; }//本题并没有定义线段树区间代表什么,所以build函数并没有实际意义
void build(int id, int l, int r) {if (l == r) {return;}int mid = (l + r) >> 1;build(ls(id), l, mid);build(rs(id), mid + 1, r);
}void pushdown(int id, int l, int r) {if (lazy[id] == 0) {//标记为0代表id区间并没有张贴海报,当然只是说该区间没有,要知道线段树中有很多区间,大区间中也有很多小区间,这点需要明确,并不是线性表,并不是线性表,并不是线性表,重要的事情说三遍return ;}//将该标记向下传递给跟小区间,相当于再次张贴海报将原有海报覆盖lazy[ls(id)] = lazy[id];lazy[rs(id)] = lazy[id];//删除标记lazy[id] = 0;
}void update(int id, int l, int r, int p, int q, int v) {if (l >= p && r <= q) {lazy[id] = v;  //v就是上文说到的编号return;}pushdown(id, l, r);  //向下覆盖int mid = (l + r) >> 1;//直到将张贴的海报的区间所覆盖的所有节点区间覆盖if (p <= mid) update(ls(p), l, mid, p, q, v);if (q > mid) update(rs(p), mid + 1, r, p, q, v);
}void query(int id, int l, int r) {if (lazy[id] && !vis[lazy[id]]) {vis[lazy[id]] = 1;  //这个数组一开始全是零ans++;return;}//注意这个判断为什么写在这里if (l == r) {return;}pushdown(id, l, r);int mid = l + r;query(ls(id), l, mid);query(rs(id), mid + 1, r);
}int main() {int t;cin >> t;while (t--) {ans = 0;memset(lazy, 0, sizeof(lazy));memset(vis, 0, sizeof(vis));cin >> n;int cnt = 1;for (int i = 1; i <= n; i++) {int a, b;cin >> left1[i] >> right1[i];num[cnt++] = left1[i];num[cnt++] = right1[i];}//先排序一次,以便第一次去重sort(num + 1, num + cnt);m = unique(num + 1, num + cnt) - (num + 1);int an = m;for (int i = 2; i <= m; i++) {if (num[i] - num[i - 1] > 1) {num[++an] = num[i - 1] + 1;  //加入中间元素,避免上文提到的离散化出现的错误}}//重新排序后,加入的中间元素回自动被插入到相应位置sort(num + 1, num + an + 1);build(1, 1, an);for (int i = 1; i <= n; i++) {int p = lower_bound(num + 1, num + an + 1, left1[i]) - num;int q = lower_bound(num + 1, num + an + 1, right1[i]) - num;update(1, 1, an, p, q, i);}query(1, 1, an);cout << ans << endl;}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/796724.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s 中的 Service 简介【k8s 系列之二】

〇、前言 k8s 集群中的每一个 Pod 都有自己的 IP 地址,那么是不是有 IP 了,访问起来就简单了呢,其实不然。 因为在 k8s 中 Pod 不是持久性的,摧毁重建将获得新的 IP,客户端通过会变更 IP 来访问显然不合理。另外 Pod 还经常会通过多个副本来实现负载均衡,客户端如何高效的…

软工作业二:论文查重系统

这个作业属于哪个课程 <计科22级34班>这个作业要求在哪里 [<作业要求>](个人项目 - 作业 - 计科22级34班 - 班级博客 - 博客园 (cnblogs.com))这个作业的目标 通过实际编程任务,全面提升学生在编程、算法、项目管理、性能优化、代码测试和版本控制等方面的能力,为…

面试-JS基础知识-作用域和闭包

问题this的不同应用场景 手写bind函数 实际开发中闭包的应用场景,举例说明 创建10个<a>标签,点击的时候弹出来对应的序号作用域:某个变量的合法使用范围全局 函数 块级** 自由变量上面图的最里面的红框————a a1 a2都是自由变量,因为都没有被定义。会一层一层往上…

学习高校课程-软件设计模式-软件设计原则(lec2)

软件设计原则Feature of Good Design (1) 优秀设计的特点(一) Code reuse 代码复用 – Challenge: tight coupling between components, dependencies on concrete classes instead of interfaces, hardcoded operations – Solution: design patterns – 挑战:组件之间的紧…

ATTCK红队评估(红日靶场4)

靶场介绍本次靶场渗透反序列化漏洞、命令执行漏洞、Tomcat漏洞、MS系列漏洞、端口转发漏洞、以及域渗透等多种组合漏洞,希望大家多多利用。 环境搭建 机器密码 WEB主机 ubuntu:ubuntuWIN7主机 douser:Dotest123(DC)WIN2008主机 administrator:Test2008网络配置111网段是web的网…

Markdown随笔

冰冻三尺非一日之寒,持之以恒方位始终。 Markdown语法讲解标题一共六级标题分别为Ctrl+1~6: 一级 二级 三级 四级 五级 六级字体 粗体 粗斜体 斜体 删除线引用一个大于号>分割线图片超链接 点击进入百度百科列表 数字加上空格(有序) 点加上空格(无序)表格姓名 性别 年…

tarjan里的定义

强连通分量 - OI Wiki (oi-wiki.org)从以u为根的子树中的任意点出发。单次到达(从这个点指向某个点,有一条边) 的这些点中的dfn的最小值以v为根的子树,包含在以u为根的子树中,low[v]所用的子节点,一定也可以被low[u],这个点一定在以u为根的子树里,所以用low[v] 从u这个…

南沙csp-j/s一对一家教陈老师解题:1317:【例5.2】组合的输出

​【题目描述】排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r≤n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r个数。 现要求你用递归的方法输出所有组合。 例如n=5,r=3,所有组合为: 1 2 3 1 2 4 1 2 5 1 3 4 1 …

First day01

Markdown学习 二级标题 字体 Hello World Hello World Hello World Hello World Hello World 引用选择java走上人生巅峰分割线图片 ![截图](C:\Users\邢其俊\Pictures\Screenshots\屏幕截图 2024-09-13 180016.png)超链接 [点击跳转到狂神博客](仓库 - 狂神说 (kuangstudy) - G…

ThreeJS Shader的效果样例光影墙、扩散面(四)

一、实现一个光影墙1. 根据自定义坐标点,输出一个光影墙/*** 添加光影墙*/ function addLightWall() {const geometry = new THREE.BufferGeometry();const vertices = new Float32Array([5, 0, 2,3, 0, 5,-2, 0, 5,-4, 0, 2,-4, 5, 2,-2, 5, 5,3, 5, 5,5, 5, 2]);const indic…

2024年youtube 视频在线下载工具

1.youtube to wav这是一个将 YouTube 视频转换为 WAV 格式的在线工具的网站链接。根据提供的信息,使用该工具的步骤如下: 开始:将 YouTube 视频的 URL 粘贴到搜索框中,然后点击 “Start” 按钮。 转换:选择转换为 WAV 的质量(推荐使用默认选项),然后点击 “Convert” 按…

Idea 配置多端口启动参数

1、编辑配置2、在弹出配置中增加要使用端口接口,添加端口参数配置、设置VM options: 参数值为: -Dserver.port= portNumber下面以应用 TranSendServiceApplication 为例,增加两个端口:8099 和8091 为例。截图如下: