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张海报,每张海报的宽度是任意的, 但是必定是单位宽度的整数 ...
随机推荐
- 3D球状标签云(兼容IE8)
看见一个很有趣的标签云,3D球状,兼容 IE 8,亲测可用!其他版本没有测试.觉得挺有意思就拿来记录下来,学习学习,本文下方会放出我看的文章地址,先看一下效果: 接下来是代码,html + css + ...
- 观察者模式(Observer)
观察者模式是经常使用到的一种设计模式,在我们的生活中也经常遇到,小到学校上学让同学帮忙看着老师有没有过来,在教室里做一些与学习无关的事情,大到股市里面我们遇到的,到股票涨到或者跌到一定程度的时候通知我 ...
- 【Sharing】开发与研发
[声明]此文为转载,只为收藏. 按:这几天我一直在写这篇东西,本来是胸有成竹,没想到后来越写越发现自己在这个题目下有太多话想说,而以我现在的能力又不能很好地概括总结,以至于越写越长,文章结构也变得混乱 ...
- seajs使用记录
关于base的默认路径: [官方说明]: 模块系统的基础路径即 base 的默认值,与 sea.js 的访问路径相关: 如果 sea.js 的访问路径是: http://example.com/ass ...
- 微信小程序视频地址
微信小程序视频系列教程完整版,课程中用到的源码附在帖子最后. [url=http://bbs.larkapp.com/forum.php?mod=viewthread&tid=5673][b] ...
- JavaScript创建对象的写法
JavaScript 有Date.Array.String等这样的内置对象,功能强大使用简单,人见人爱,但在处理一些复杂的逻辑的时候,内置对象就很无力了,往往需要开发者自定义对象. 对象是什么 从 ...
- 你必须知道的.NET
作者博客地址:http://www.cnblogs.com/anytao/archive/2008/04/09/anytao_insidenet_center.html 第1章 OO大智慧 1.1对象 ...
- Oracle 10g RAC 启动与关闭
一. 检查共享设备 一般情况下,存放OCR和Voting Disk的OCFS2 或者raw 都是自动启动的. 如果他们没有启动,RAC 肯定是启动不了. 1.1 如果使用ocfs2的 检查ocfs2 ...
- Spark 大数据平台
Apache Spark is an open source cluster computing system that aims to make data analytics fast - both ...
- windows环境下MySQL重启的命令行说明
ctrl+r 弹出运行框,输入cmd,然后再控制太输入命令: 1.点击“开始”->“运行”(快捷键Win+R). 2.停止:输入 net stop mysql 3.启动:输入 net start ...