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张海报,每张海报的宽度是任意的, 但是必定是单位宽度的整数 ...
随机推荐
- 精简DropDownList用法
ViewBag.TypeID = new SelectList(db.TType, "ID", "Name", model.TypeID); @Html.Dro ...
- 阿里云服务器 ECS Ubuntu系统安装配置
1. 登陆服务器 系统开通成功后手机会收到阿里云发来的短信,包含公网IP及root登录密码. WEB管理后台方式 可通过阿里云管理后台选择“连接管理终端…”进行登录 提示输入VNC密码 登录成功后显示 ...
- jQuery插件使用大全
1.jQuery datepicker日历插件使用说明 http://wenku.baidu.com/view/12804e1e59eef8c75fbfb3e3 2.jqueryFileUpload插 ...
- jquery 在页面中三种写法
jQuery 分 2 个系列版本 1.x 与 2.x,主要的区别在于 2.x 不再兼容 IE6.7.8浏览器,这样做的目的是为了兼容移动端开发.由于减少了一些代码,使得该版本比 jQuery 1.x ...
- windows下apache配置https
1.下载带有openSSL的apache安装包,我下载的为apache_2.2.11-win32-x86-openssl-0.9.8i.msi,安装后确认一下bin路径下的openssl.exe,ss ...
- linux服务器修改ssh默认22端口方法
1.登录服务器,打开sshd_config文件 # vim /etc/ssh/sshd_config 2.找到#Port 22,默认是注释掉的,先把前面的#号去掉,再插入一行设置成你想要的端口号,注意 ...
- 百度云盘demo
- oracle-12c-rac 报:ORA-01078
OS: Oracle Linux Server release 5.7 DB: Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - ...
- Linux下Hadoop的简单安装
Hadoop 的安装极为简单,一共只有三步: 安装JDK 安装Hadoop 配置Hadoop 1,安装JDK 下载JDK,ftp传到linux或者linux中下载 切换 ...
- 【quartz】 数据库方式管理任务
public static void Run(bool inClearJobs, bool inScheduleJobs) { var properties = new NameValueCollec ...