题目

在长度为L的宣传栏上张贴N张海报,将宣传栏分为L个长度为1的单位,海报长度为整数,且高度和宣传栏相同,左右边界和宣传栏单位之间缝隙重合(即海报总是跨越整数个单位)。后贴的海报可能会覆盖之前贴的海报的全部或者部分,问N张海报贴完之后,没有被完全覆盖的海报的总数。N <= 10^6, L <= 10^9.

分析

区间覆盖问题,会想到用线段树来解决,直观的将L个单位视为线段树的叶子节点,但是这样做空间复杂度太高(同样时间复杂度也很高),可以将区间进行离散化: 
    将所有海报的边界先收集起来,按照从小到大排序后去重,这样得到的离散点映射到从0开始,每次增加1的一个区间上,然后将该区间映射到线段树上。 
    线段树的节点结构中维护两个信息:(1)该节点代表的区间是否只有一个海报single_post,(2)如果只有一个海报,则记录海报序号post。 
    插入海报的时候,找到海报的左右边界点对应到线段树的叶节点编号构成的区间A,然后从根节点开始递归,如果到达某个节点,该节点代表区间B和A相同,则设置该节点的single_post为true,且post为海报号,否则向下找; 
    最后查询的时候,从线段树根节点开始向下找,找到所有的区间内只有一个海报的节点,并将海报号记录下来。

实现

#include<iostream>
#include<string.h>
#include<iostream>
#include<queue>
#include<cmath>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int inf = 1 << 29;
const int kMax = 200005;
unordered_map<int, int> discrete_map; //海报所贴的端点到线段树区间端点的映射
int gPost[kMax >> 1][2]; //海报的左右边界
vector<int> gPoints; //存放海报的端点
unordered_set<int> uncovered_post; //没有被遮盖的海报序号
struct Node{
int beg;
int end;
int post;
bool single_post;
Node(){
beg = end = 0;
single_post = true;
post = -1;
}
};
Node gNodes[kMax << 2]; //连续型的区间 线段树
void BuildTree(int node, int beg, int end){
gNodes[node].beg = beg;
gNodes[node].end = end;
if (beg + 1 == end){
//连续型的区间,线段树的叶子节点表示一个单位长度[i, i+1],而不是一个点[i, i].
return;
}
int mid = (beg + end) >> 1;
int left = 2 * node + 1, right = 2 * node + 2;
BuildTree(left, beg, mid);
BuildTree(right, mid, end);
//连续型的区间,[beg, mid] & [mid, end]; 而离散型的区间[beg, mid]&[mid + 1, end]
} void PushDown(int node){
if (gNodes[node].beg + 1 == gNodes[node].end)
return;
if (gNodes[node].single_post){
int left = 2 * node + 1, right = 2 * node + 2;
gNodes[left].post = gNodes[right].post = gNodes[node].post;
gNodes[left].single_post = gNodes[right].single_post = true;
gNodes[node].single_post = false;
}
} void Post(int node, int beg, int end, int post){
if (gNodes[node].beg == beg && gNodes[node].end == end){
gNodes[node].single_post = true;
gNodes[node].post = post;
return;
}
PushDown(node);
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (gNodes[node].beg + gNodes[node].end) / 2;
if (beg >= mid){
Post(right, beg, end, post);
}
else if (end <= mid){
Post(left, beg, end, post);
}
else{
Post(left, beg, mid, post);
Post(right, mid, end, post);
}
}
void Query(int node){
if (gNodes[node].single_post && gNodes[node].post != -1){
uncovered_post.insert(gNodes[node].post);
return;
}
if (gNodes[node].beg + 1 == gNodes[node].end){
return;
}
int left = 2 * node + 1, right = 2 * node + 2;
Query(left);
Query(right);
} int main(){
int N, L;
scanf("%d %d", &N, &L);
for (int i = 0; i < N; i++){
scanf("%d %d", &gPost[i][0], &gPost[i][1]);
//将各个离散点加入vector
gPoints.push_back(gPost[i][0]);
gPoints.push_back(gPost[i][1]);
} //先排序
sort(gPoints.begin(), gPoints.end()); //对vector去重
gPoints.resize(std::distance(gPoints.begin(), unique(gPoints.begin(), gPoints.end()))); BuildTree(0, 0, gPoints.size() - 1);
//将离散化的点,按照大小映射到一个连续的区间,缩小数据规模
for (int i = 0; i < gPoints.size(); i++){
discrete_map[gPoints[i]] = i;
}
for (int i = 0; i < N; i++){
Post(0, discrete_map[gPost[i][0]], discrete_map[gPost[i][1]], i);
}
Query(0);
int result = uncovered_post.size();
printf("%d\n", result);
return 0;
}

hiho_1079_离散化的更多相关文章

  1. NBUT 1457 莫队算法 离散化

    Sona Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format: Submit Status Practice NBUT 145 ...

  2. 项目安排(离散化+DP)

    题目来源:网易有道2013年校园招聘面试二面试题 题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的 ...

  3. P1774 最接近神的人_NOI导刊2010[树状数组 逆序对 离散化]

    题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的 ...

  4. 洛谷P1462 通往奥格瑞玛的道路[二分答案 spfa 离散化]

    题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描述 在艾泽拉斯, ...

  5. POJ1151Atlantis 矩形面积并[线段树 离散化 扫描线]

    Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 21734   Accepted: 8179 Descrip ...

  6. POJ2528Mayor's posters[线段树 离散化]

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 59683   Accepted: 17296 ...

  7. HDU 3333 | Codeforces 703D 树状数组、离散化

    HDU 3333:http://acm.hdu.edu.cn/showproblem.php?pid=3333 这两个题是类似的,都是离线处理查询,对每次查询的区间的右端点进行排序.这里我们需要离散化 ...

  8. HDU 3743 Frosh Week (线段树+离散化)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 Frosh Week Time Limit : 2000/1000ms (Java/Other) ...

  9. Hihocoder 1079 离散化

    离散化这里有很多种方式 利用结构体记录最初的索引在按位置排序再记录排名即为离散的位置再按索引排回来 或者用数组记录排序后直接对原位置二分直接去找离散应在的位置 或者对数组排序后直接map 3 20 1 ...

随机推荐

  1. 项目文件中含有两个config文件,app.config与app1.config,如何获取app1.config中的配置

    想要通过配置文件配置C#前台画面,好奇做了以下测试:在项目中新建了app.config与app1.config两个配置文件,请教一下各位高手如果想从app1.config中读取配置信息应该如何读取?采 ...

  2. vs智能提示突然消失的解决办法 (vs2008 vs2010 vs2012 智能提示)

    vs智能提示突然消失的解决办法 (vs2008 vs2010 vs2012 智能提示) 下面一段话是网上找到的解决方案: 重置Visual Studio可以解决此问题,方法是从开始->Micro ...

  3. 2016年10月25日 星期二 --出埃及记 Exodus 19:9

    2016年10月25日 星期二 --出埃及记 Exodus 19:9 The LORD said to Moses, "I am going to come to you in a dens ...

  4. Jams倒酒(pour)

    1.Jams倒酒(pour) Jams是一家酒吧的老板,他的酒吧提供2种体积的啤酒,a ml 和 b ml,分别使用容积为a ml 和 b ml的酒杯来装载. 酒吧的生意并不好.Jams发现酒鬼们都很 ...

  5. mfc学生成绩录入与查询

    1.声明结构体 struct Person{ char name[8]; char yuwen[8]; char math[8];}; 2.成绩录入 在"保存"按钮中实现以下代码 ...

  6. Xcode插件管理以及Xcode7 升级

    一,Xcode插件管理工具 Alcatraz: mkdir -p ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins; cur ...

  7. iOS深入学习(UITableView:系列1-最基本的东西)

    这是UITableView博客系列的第一篇,使用xib和arc编码,主要讲解一些UITableView使用过程中简单的.但是又容易被忽略的东西,而且我会告诉读者,怎样在使用了之后就再也不会忘记. 操作 ...

  8. jquery之 off()方法

    off()函数用于移除元素上绑定的一个或多个事件的事件处理函数. off()函数主要用于解除由on()函数绑定的事件处理函数. 该函数属于jQuery对象(实例). 语法 jQuery 1.7 新增该 ...

  9. Date Picker Calendar For Oracle Forms 6i

    Giving date picker calendar option to user for date type fields in Oracle Forms. I am providing you ...

  10. CUBRID学习笔记 18 sql语句的预处理(类似存储过程)

    定义预处理  类似sqlserver的存储过程 语法 PREPARE stmt_name FROM preparable_stmt 说明 PREPARE 关键字 stmt_name 预处理语句的名字 ...