做这题建议看一下该题的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 (线段树,染色问题,离散化要注意)的更多相关文章

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

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

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

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

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

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

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

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

  5. poj 2528 Mayor's posters 线段树+离散化技巧

    poj 2528 Mayor's posters 题目链接: http://poj.org/problem?id=2528 思路: 线段树+离散化技巧(这里的离散化需要注意一下啊,题目数据弱看不出来) ...

  6. poj 2528 Mayor's posters 线段树区间更新

    Mayor's posters Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Descript ...

  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 线段树+离散化 || hihocode #1079 离散化

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

  9. POJ 2528 Mayor's posters (线段树)

    题目链接:http://poj.org/problem?id=2528 题目大意:有一个很上的面板, 往上面贴海报, 问最后最多有多少个海报没有被完全覆盖 解题思路:将贴海报倒着想, 对于每一张海报只 ...

  10. poj 2528 Mayor's posters(线段树)

    题目:http://poj.org/problem?id=2528 题意:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意的, 但是必定是单位宽度的整数 ...

随机推荐

  1. 济南学习 Day 4 T2 am

    LYK 与实验室(lab)Time Limit:5000ms Memory Limit:64MB题目描述LYK 在一幢大楼里,这幢大楼共有 n 层,LYK 初始时在第 a 层上.这幢大楼有一个秘密实验 ...

  2. php 文件上传一例简单代码

    1.程序文件 <?php //判断临时文件存放路径是否包含用户上传的文件 if(is_uploaded_file($_FILES["uploadfile"]["tm ...

  3. DataSnap数据库连接池,数据集对象池的应用

    传统的应用服务器的开发往往是在ServerMethods单元中拖放一堆TDataSet, TDaTaSetProvider控件,这是一个最简单粗暴的开发方向,往往会造成服务端程序文件的臃肿.服务运行期 ...

  4. python学习第四天第一部分

    1.字典的特性:无序.去重.查询速度快.比list占用内存多. 2.字典查询速度快的原因:因为他是哈希类型的. 3.什么是(hash)哈希? hash把任意长度的二进制映射为较短的固定长度的二进制,这 ...

  5. 如何在SAE上使用DjangoUeditor

    之前的一个项目是部署到SAE上的,其中富文本编辑器使用到了Ueditor,对于Django有一个开源项目DjangoUeditor可以简化继承过程,直接引用app就可以使用.但是不支持SAE的文件上传 ...

  6. 简单的优化处理 By LINQ TO SQL

    最近在做关于新浪微博授权的一些minisite,数据库并不复杂,所以在数据打交道这块采用了linqtosql,开发起来更快更简单...但是随着用户访问逐渐增多,用户上传的图片也越来越多,因为首页是一个 ...

  7. zendframework 事件管理(二)

    首先需要明确的几个问题: Q1.什么是事件? A:事件就是一个有名字的行为.当这个行为发生的时候,称这个事件被触发. Q2.监听器又是什么? A:监听器决定了事件的逻辑表达,由事件触发.监听器和事件往 ...

  8. PAT IO-04 混合类型数据格式化输入(5)

    /* *PAT IO-04 混合类型数据格式化输入(5) *2015-08-01 作者:flx413 */ #include<stdio.h> int main() { int a; fl ...

  9. 爱重启的windows,伤不起

    .

  10. Thinkphp常用的方法和技巧(转)

    2012年09月26日 Thinkphp 里一些常用方法和技巧的整理,包括常用的快捷键以及在程序开发时用到的一些实用方法,关于快捷键用得不是很熟练,总之,掌握这些方法和技巧,对于我们开发 thinkp ...