POJ 2528 Mayor's posters (线段树,染色问题,离散化要注意)
做这题建议看一下该题的discuss。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <set>
/* 题意:给出n张海报的左端点和右端点,按顺序往墙上贴。问最后整张墙能看到几张海报。 注意:按题意是如此够造树的,即每个点其实是一小块段。
|___|___|___|___|___|___|___|___|
1 2 3 4 5 6 7 8 思路:相当于染色问题,这里我每个节点有个color值。
color值有三种情况:1.0表示该区间为染色;2.-1表示该区间含有多种颜色;3.正整数表示该区间全是一种颜色
每次更新(即第i次“涂色”)的时候,如果区间在范围内,则该区间color值替换为此次的颜色(用i表示)。
最后查询的时候,从根节点往下查,直到查询到color值为某一个正整数,标记该颜色对应的序号。
最后统计有多少个标记,即为答案。 由于数据大,要离散化,这才是重点!!!
有些人离散化,直接按顺序相邻,即每次都只加1。这是错误的!!!
给个数据就明白了:
1
3
1 10
1 3
6 10
正确答案:3
错误答案:2
忽略了顺序相邻但位置不相邻的情况
如果直接按顺序离散:
1 4
1 2
3 4
那么1 2和3 4的就会覆盖掉1 4,得出错误结果2
即离散的时候3和6之间应该还要留出一段,即总共离散为5段,不然会把中间夹的给覆盖掉了 所以离散的时候,排好序后,如果两个相邻的仅相差1,那么对应的映射+1即可。
但如果相差大于1,则对应的映射+2,留出个空隙。 在discuss里会有人说,如果按这正确的方法做,提交会WA;全部改成+1,才AC。
其实+2导致WA的原因,是数组开的不够。
我原本开的是tree[maxn<<3]的大小,用正确做法做,WA;但开大后,tree[maxn<<4],就AC了。
也就是说,POJ上其实没有这类数据 */
using namespace std;
const int maxn=;
int n,m,idx;
int maxh; //对应映射的最大值
int hash_val[]; //对应的映射
int val[maxn*]; //存储端点的值
int vis[maxn]; //用来标记颜色
//存储海报的左端点、右端点
struct Pos{
int left,right;
}pos[maxn]; struct Node{
int color; //0:该区间没有染色;-1:该区间含多种颜色;正整数:该区间涂满一种颜色。
bool lazy;
}tree[maxn<<]; //10000个海报,每个海报两个端点,所以最多会有20000个点,但开4倍不够,要开8倍,这样+2的方法才能AC void build(int rt,int L,int R){
tree[rt].color=;
tree[rt].lazy=false;
if(L==R)
return;
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid+,R);
} void pushUp(int rt){
int lson=rt<<,rson=rt<<|;
//只要有一个子区间上面含多种颜色(color值为-1),该节点color值为-1
if(tree[lson].color==- || tree[rson].color==-)
tree[rt].color=-;
//两个子区间都没涂有颜色
else if(!tree[lson].color && !tree[rson].color)
tree[rt].color=;
//两个子区间各自都涂有一种颜色
else if(tree[lson].color && tree[rson].color){
if(tree[lson].color==tree[rson].color)
tree[rt].color=tree[lson].color;
else
tree[rt].color=-;
}
else{
//一个为0(即该区间没有染色),另一个为正数
tree[rt].color=tree[lson].color|tree[rson].color;
}
}
void pushDown(int rt){
if(tree[rt].lazy){
int lson=rt<<,rson=rt<<|;
tree[lson].color=tree[rson].color=tree[rt].color;
tree[lson].lazy=tree[rson].lazy=true;
tree[rt].lazy=false;
}
}
void update(int rt,int l,int r,int L,int R,int color){
if(l<=L && R<=r){
tree[rt].lazy=true;
tree[rt].color=color;
return;
}
pushDown(rt);
int mid=(L+R)>>;
if(r<=mid)
update(rt<<,l,r,L,mid,color);
else if(l>mid)
update(rt<<|,l,r,mid+,R,color);
else{
update(rt<<,l,mid,L,mid,color);
update(rt<<|,mid+,r,mid+,R,color);
}
pushUp(rt);
}
void query(int rt,int L,int R){
//下面两种情况已经包含了叶子节点,因为叶子节点的color只能为0或者>0,不可能为-1。所以不会RE
if(tree[rt].color>){
//如果该区间涂有一种颜色,则标记该颜色
vis[tree[rt].color]=;
return;
}
//如果区间没有染色,直接return。
if(!tree[rt].color){
return;
}
int mid=(L+R)>>;
query(rt<<,L,mid);
query(rt<<|,mid+,R);
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
idx=;
for(int i=;i<=n;i++){
scanf("%d%d",&pos[i].left,&pos[i].right);
val[idx++]=pos[i].left;
val[idx++]=pos[i].right;
}
sort(val,val+idx);
hash_val[val[]]=;
//离散
for(int i=;i<idx;i++){
if(val[i]==val[i-])
hash_val[val[i]]=hash_val[val[i-]];
//如果两个端点不相邻,则+2
else if(val[i]-val[i-]>)
hash_val[val[i]]=hash_val[val[i-]]+; //如果两个端点相邻,则+1.
else{
hash_val[val[i]]=hash_val[val[i-]]+;
}
maxh=hash_val[val[i]];
}
build(,,maxh);
for(int i=;i<=n;i++){
update(,hash_val[pos[i].left],hash_val[pos[i].right],,maxh,i);
}
memset(vis,,sizeof(vis));
query(,,maxh);
int ans=;
for(int i=;i<=n;i++){
if(vis[i]){
ans++;
}
}
printf("%d\n",ans);
}
return ;
}
POJ 2528 Mayor's posters (线段树,染色问题,离散化要注意)的更多相关文章
- POJ 2528 Mayor's posters (线段树区间更新+离散化)
题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值 ...
- POJ 2528 Mayor’s posters (线段树段替换 && 离散化)
题意 : 在墙上贴海报, n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000).求出最后还能看见多少张海报. 分析 ...
- POJ 2528 Mayor's posters (线段树+区间覆盖+离散化)
题意: 一共有n张海报, 按次序贴在墙上, 后贴的海报可以覆盖先贴的海报, 问一共有多少种海报出现过. 题解: 因为长度最大可以达到1e7, 但是最多只有2e4的区间个数,并且最后只是统计能看见的不同 ...
- POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)
POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...
- poj 2528 Mayor's posters 线段树+离散化技巧
poj 2528 Mayor's posters 题目链接: http://poj.org/problem?id=2528 思路: 线段树+离散化技巧(这里的离散化需要注意一下啊,题目数据弱看不出来) ...
- poj 2528 Mayor's posters 线段树区间更新
Mayor's posters Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Descript ...
- POJ 2528 Mayor's posters(线段树+离散化)
Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...
- poj 2528 Mayor's posters 线段树+离散化 || hihocode #1079 离散化
Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the ...
- POJ 2528 Mayor's posters (线段树)
题目链接:http://poj.org/problem?id=2528 题目大意:有一个很上的面板, 往上面贴海报, 问最后最多有多少个海报没有被完全覆盖 解题思路:将贴海报倒着想, 对于每一张海报只 ...
- poj 2528 Mayor's posters(线段树)
题目:http://poj.org/problem?id=2528 题意:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意的, 但是必定是单位宽度的整数 ...
随机推荐
- OpenGL第6、7讲小结
因为内容比较多,所以只看了两讲(强行解释). 一讲讲了如何给各个面贴纹理,一讲讲了加光照和按键控制. 现在讲的都是给规则的面贴纹理,像正方形,刚好纹理图也是正方形,那像人物模型的衣服贴起来用代码控制得 ...
- iOS 非ARC基本内存管理系列总结6 -设计微博模型
设计简单的微博模型:用User类和Status类来模拟实现 在非ARC机制下有两种方式,两者没有太大的区别之所以写了两种只是为了方便学习和对比两种写法! 第一种:没有使用atuorelease和自动释 ...
- Centos(Linux) 根文件系统
/下面的文件 /boot:系统启动相关的文件:如内核,inittrd ,以及MBR grub /dev :设备文件: 块设备:随机访问,数据块 如:USB 字符设备:线性访问,按字符为单位如:鼠标,按 ...
- shell 字符截取
Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.aaa.com/123.htm. # 读sharp 谐音 杀: ${var#*//} 杀掉//左边的,保留右边的 ...
- 一个好用的PHP验证码类
分享一个好用的php验证码类,包括调用示例. 说明: 如果不适用指定的字体,那么就用imagestring()函数,如果需要遇到指定的字体,就要用到imagettftext()函数.字体的位置在C盘下 ...
- 重拾C,一天一点点_5
switch(表达式){ case 整型常量表达式:语句序列 case 整型常量表达式:语句序列 default:语句序列} while(表达式) 语句 for(表达式1; 表 ...
- 画了一张PHPCMSV9的运行流程思维导图
转载:http://www.cnblogs.com/fuyunbiyi/archive/2012/03/12/2391253.html
- 拥抱ARM妹纸第二季 之 第一次 点亮太阳
上次做鱼缸LED灯时还有很多材料正好拿来用.穆等等哥- 俺去找材料. 材料列表 3W LED x 3 散热片 x 1 恒流IC x 1 其他零 ...
- Linux下Hadoop的简单安装
Hadoop 的安装极为简单,一共只有三步: 安装JDK 安装Hadoop 配置Hadoop 1,安装JDK 下载JDK,ftp传到linux或者linux中下载 切换 ...
- python之类定义
<python基础教程>第7章说python中的类定义: 1. 要么声明__metaclass__=type 2. 要么继承object. 但是直接定义下类, 也没报错: >> ...