由于题面中给定的wall最大长度为10 000 000;若简单用线段树势必会超时。

而注意到题面中规定了输入海报的个数<=1000;因此不妨离散化,使得线段中叶节点仅含有1000个,那么线段最大深度为10,不会TLE。

同时在构造线段树的时候除了设置基本的长度变量l,r之外,

设置了一个新的变量kind用于储存当前线段的覆盖状态(=0表示没有覆盖或有多个覆盖;=1表示只有一个覆盖)。这样当计算最终状态时只需要对  遍历到的每一个kind不为0的线段  计数值加1。同时线段的搜索也在这里终止(因为若上层线段已经覆盖,那么下层必然也被覆盖,因而不需重复搜索)。

这是本题解题的关键,也是体现线段树结构特色的地方,值得好好品味,很轻巧的构造。

此外在解题中出现了两次bug:

1、sort()范围出错,由于是从1位置开始而非0位置,因此范围需要+1;

2、使用map报TLE,改为int数组后AC。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
//代码原本使用map来记录位置和编号的映射,但是TLE;改成int数组后就ac了。stl还是要慎用。
//编程思路:先想清楚算法,先实现数据结构,再写主函数
const int maxn=+;
struct line{
int l,r,kind;//这个kind的记录是精华
}tree[maxn*];//这个数量的判定 (1000的叶子,最多10层,取最大值10*maxn) int l[maxn],r[maxn];
int poster[maxn*];//记录海报的所有坐标,离散化 void build(int l,int r,int node){
tree[node].l=l,tree[node].r=r;
if(l==r)return;
int mid=(l+r)/;
build(l,mid,node*);
build(mid+,r,node*+);
} void update(int l,int r,int node,int k){
if(tree[node].l==l&&tree[node].r==r){
tree[node].kind=k;//完全覆盖
return;
}
if(tree[node].kind==k)return ;
// if(tree[node].kind!=0){//这里的细微差别个人感觉没啥影响(包括上面一行是否有必要存在的问题)
if(tree[node].kind!=&&tree[node].kind!=k){
tree[node*].kind=tree[node].kind;
tree[node*+].kind=tree[node].kind;
tree[node].kind=;
}
if(r<=tree[node*].r){
update(l,r,node*,k);
}
else if(l>=tree[node*+].l){
update(l,r,node*+,k);
}
else{
update(l,tree[node*].r,node*,k);
update(tree[node*+].l,r,node*+,k);
}
} int result=;
bool flag[maxn];
void cal(int node){
if(tree[node].kind!=){
if(flag[tree[node].kind]==false){
result++;
// cout<<tree[node].l<<" "<<tree[node].r<<" "<<tree[node].kind<<endl;//test
flag[tree[node].kind]=true;
}
}
else{
cal(node*);
cal(node*+);
}
} int pos2no[] ; int main(void){
int t;
scanf("%d",&t);
while(t--){
memset(tree,,sizeof(tree));
memset(flag,false,sizeof(flag));
memset(poster,,sizeof(poster));
memset(pos2no,,sizeof(pos2no));
int n;
scanf("%d",&n);
int j=;
for(int i=;i<=n;i++){//从1开始编号
scanf("%d%d",&l[i],&r[i]);
poster[++j]=l[i];poster[++j]=r[i];
}
sort(poster+,poster+j+);//排序去重 ;注意为什么是j+1 (wa点)
int len=j,k=;
for(int i=;i<=len;i++,k++){
poster[k]=poster[i];
while(poster[i]==poster[i+])i++;
}
int finlen=k-;
//map<int,int> pos2no;//位置到编号的映射 若使用map也是正确的,但是会报TLE,故弃之。 for(int i=;i<=finlen;i++){
pos2no[poster[i]]=i;
}
build(,finlen,) ;
for(int i=;i<=n;i++){
update(pos2no[l[i]],pos2no[r[i]],,i);
}
result=;
cal();
printf("%d\n",result);
}
return ;
}

poj_2528 Mayor's posters (线段树经典题+离散化方法)的更多相关文章

  1. POJ 2528 Mayor's posters (线段树区间更新+离散化)

    题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...

  2. POJ2528:Mayor's posters(线段树区间更新+离散化)

    Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...

  3. POJ 2528 Mayor’s posters (线段树段替换 && 离散化)

    题意 : 在墙上贴海报, n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000).求出最后还能看见多少张海报. 分析 ...

  4. POJ 2528 Mayor's posters (线段树+区间覆盖+离散化)

    题意: 一共有n张海报, 按次序贴在墙上, 后贴的海报可以覆盖先贴的海报, 问一共有多少种海报出现过. 题解: 因为长度最大可以达到1e7, 但是最多只有2e4的区间个数,并且最后只是统计能看见的不同 ...

  5. POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)

    POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...

  6. [poj2528] Mayor's posters (线段树+离散化)

    线段树 + 离散化 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayor ...

  7. POJ 2528 Mayor's posters(线段树+离散化)

    Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...

  8. POJ 2528 Mayor's posters (线段树+离散化)

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

  9. poj 2528 Mayor's posters 线段树+离散化 || hihocode #1079 离散化

    Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the ...

随机推荐

  1. (转)聊聊Servlet、Struts1、Struts2以及SpringMvc中的线程安全

    前言 很多初学者,甚至是工作1-3年的小伙伴们都可能弄不明白?servlet Struts1 Struts2 springmvc 哪些是单例,哪些是多例,哪些是线程安全? 在谈这个话题之前,我们先了解 ...

  2. 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件

    本文背景: 在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用:根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制. 本 ...

  3. 【我的Android进阶之旅】Jenkins挂载slave节点,增强分布式编译的效率

    由于公司的Jenkins任务越来越多,而且所有的Android Jenkins任务都在同一台服务器上进行编译,而且该服务器配置Jenkins任务最多3个任务同时运行,所以有时候大家一起编译的时候,只能 ...

  4. linux下安装mysql(mariadb)

    yum安装软件(官网很慢) yum install mariadb 发现版本如下,版本特别低,且安装包特别小, mariadb x86_64 :-.el7_5 base 8.9 M .我们可以配置ma ...

  5. node.js---sails项目开发

    http://sailsdoc.swift.ren/ 这里有 sails中文文档 node.js---sails项目开发(1)安装,启动sails node.js---sails项目开发(2)安装测试 ...

  6. matlab实现MSER(最大极值稳定区域)来进行文本定位

    一.自然场景文本定位综述   场景图像中文本占据的范围一般都较小,图像中存在着大范围的非文本区域.因此,场景图像文本定位作为一个独立步骤越来越受到重视.这包括从最先的CD和杂志封面文本定位到智能交通系 ...

  7. 深入理解Oracle调试事件:10046事件详解

    10046事件是SQL_TRACE的扩展,被戏称为"吃了兴奋剂的SQL_TRACE"       有效的追踪级别:              ① 0级:SQL_TRACE=FASL ...

  8. ORACLE USERENV函数

    ORACLE USERENV函数 USERENV返回关于当前会话的信息.此信息可以用于编写一个应用程序特定的审计跟踪表或确定特定于语言的角色目前使用的会话. 参数 功能 CLINET_INFO 返回最 ...

  9. Leetcode 357

    没用过Leetcode刷题,只能按照自己的想法随便写写了 思路:1.第一位数有9种(除了0)可能,第二位数有9种(除了第一位)可能,第三位数有8种(除了前两位)可能,以此类推...9*8*7*...( ...

  10. iClap:产品经理再忙也要看《琅琊榜》

    最先知道<琅琊榜>,是半年前偶然看了整整21分钟的<琅琊榜>片花,对麒麟才子梅长苏这一角色甚是期待,开播后每集必看,重复看,此剧果真不负众望,口碑爆棚,收视爆红,确是一部久违的 ...