由于题面中给定的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. getResource()和getResourceAsStream以及路径问题(转)

    用JAVA获取文件,听似简单,但对于很多像我这样的新人来说,还是掌握颇浅,用起来感觉颇深,大常最经常用的,就是用JAVA的File类,如要取得c:/test.txt文件,就会这样用File file ...

  2. CentOS中文乱码问题的解决方法

    一.CentOS系统访问 xxx.cn ,发现中文乱码于是用以前的方式:# yum -y install fonts-chinese # yum -y install fonts-ISO8859 Ce ...

  3. Java 之设计模式(总述)

    1. 面向对象设计原则 单一职责原则: 一个类只负责一个功能领域中的相应职责 开闭原则: 软件实体应对扩展开放,而对修改关闭; 里氏代换原则: 所有引用基类对象的地方能够透明地使用其子类的对象; 依赖 ...

  4. Windows上安装zabbix客户端

    1.下载解压 https://www.zabbix.com/downloads/3.4.0/zabbix_agents_3.4.0.win.zip conf目录下放有agent配置文件 bin目录下有 ...

  5. Python高级特性(3): Classes和Metaclasses(转)

    原文:Python高级特性(3): Classes和Metaclasses 类和对象 类和函数一样都是Python中的对象.当一个类定义完成之后,Python将创建一个“类对象”并将其赋值给一个同名变 ...

  6. java7(1)——反编译深入理解增强的switch(读字节命令实战)

    [本文介绍] 本文主要讲java_7 的改进switch的底层实现.反编译一个使用带String的switch的demo并一步步解析反编译出来的字节命令,从编译的角度解读switch的底层实现. [正 ...

  7. JavaScript Big-Int

    这个库是为JavaScript中的大整数操作,如加,减,乘,除,mod,比较等. 这个库的原理是模拟笔和纸的操作,你可以操作整数,大到你的RAM允许. 例 var bigInt = require(' ...

  8. ruby on rails 数据库操作

    (1)增加列的操作 rails generate migration add_password_digest_to_students password_digest:string bundle exe ...

  9. javaScript动画3 事件对象event onmousemove

    事件对象的获取(event的获取) var event = event || window.event;(主要用这种) screenX.pageX和clientX的区别 PageY/pageX: 鼠标 ...

  10. 关于jQuery获得表单radio类型输入框的选中值

    var item=$("input[name='w1']checked").val(); 下面这句,问题解决(加上[type='radio']:): var item=$(&quo ...