POJ2528 Mayor's posters(线段树染色问题+离散化)
题目大意:有t组数据,每组数据给你n张海报(1<=n<=10000),下面n组数据分别给出每张海报的左右范围(1 <= l <= r <= 10000000),下一张海报会覆盖前一张海报,求最后可见(包括完全和不完全可见)的海报有几张。
例如:
1
5
1 4
2 6
8 10
3 4
7 10

如上图所示,答案为4。
解题思路:其实这是一道区间染色问题,但是由于查找区间太大,显然直接建树会导致MLE,所以这里通过使用对区间的离散化来缩小查找范围。参考了一些大牛博客,简单说一下。
通俗点说,离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:
有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9]。现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9。删除相同点并对其升序排序,得2 3 4 6 8 9 10
然后建立映射
2 3 4 6 8 9 10
↓ ↓ ↓ ↓ ↓ ↓ ↓
1 2 3 4 5 6 7
那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6。
但是对于这道题目来说,这样简单的离散化是不行的,比如三张海报为:1~10、1~4、7~10,就有区间[1,10],[1,4],[7,10]。
按照上述方法离散化后的到区间[1,4],[1,2],[3,4]。答案为2,实际上答案为3。
因为上述做法忽略了区间[2,3]的存在,也就是原来的5~6这一块。
新的离散方法为:在相差大于1的数间加一个数(我选择加入两个数的中间值),这样的含义是用一个数字来表示其中间的那块区间,解决某块区间被忽略的问题。
例如在上面1 4 6 10中,
X[ 1 ] = 1, X[ 2 ]=2,X[ 3 ] = 4,X[ 4 ] = 5, X[ 5 ] = 7,X[ 6 ]=8, X[ 7 ] = 10
这样之后,第一次是1~7被染成1;第二次1~3被染成2;第三次5~7被染成3
最终,1~3为2,4为1,5~7为3,于是输出正确结果3。
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#define LC(a) ((a<<1))
#define RC(a) ((a<<1)+1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long ll;
const int N=5e4*; struct node{
ll l,r;
ll color;//颜色为-1表示混合色
}tree[N]; struct knode{
ll l,r;//用来存储题目给定的区间
}tmp[N]; ll ans[N];//记录颜色i是否存在
ll Hash[N];//存储坐标映射
ll point[N];//存储坐标序列
//下推
void pushdown(ll p){
tree[RC(p)].color=tree[LC(p)].color=tree[p].color;
}
//上推
void pushup(ll p){
tree[p].color=(tree[LC(p)].color==tree[RC(p)].color?tree[LC(p)].color:-);
} void build(ll p,ll l,ll r){
tree[p].l=l;
tree[p].r=r;
tree[p].color=;
if(l==r){
return;
}
build(LC(p),l,MID(l,r));
build(RC(p),MID(l,r)+,r);
} void update(ll p,ll l,ll r,ll color){
if(r<tree[p].l||l>tree[p].r)
return;
if(l<=tree[p].l&&r>=tree[p].r){
tree[p].color=color;
return;
}
//**释放lazy标记
if(tree[p].color!=-){
pushdown(p);
}
update(LC(p),l,r,color);
update(RC(p),l,r,color);
pushup(p);
} void query(ll p,ll l,ll r){
if(r<tree[p].l||l>tree[p].r)
return;
//纯色,不用再找下去
if(tree[p].color!=-){
ans[tree[p].color]=;
return;
}
query(LC(p),l,r);
query(RC(p),l,r);
} //二分查找
ll Bin_search(ll l,ll r,ll x){
ll mid;
while(l<=r){
mid=(l+r)/;
if(x==Hash[mid]) return mid;
if(x<Hash[mid]) r=mid-;
else if(x>Hash[mid]) l=mid+;
}
return -;
} int main(){
ios::sync_with_stdio(false);
ll t,n;
cin>>t;
while(t--){
cin>>n;
//***对输入数据进行离散化
ll m1=; for(int i=;i<=n;i++){
ll l,r;
cin>>tmp[i].l>>tmp[i].r;
point[++m1]=tmp[i].l;
point[++m1]=tmp[i].r;
}
sort(point+,point++m1);
ll m2=;
for(int i=;i<=m1;i++){
if(point[i]!=point[i-]){
if(point[i]-point[i-]>&&i!=){
Hash[++m2]=(point[i]+point[i-])>>;
Hash[++m2]=point[i];
}
else
Hash[++m2]=point[i];
}
}
//**建树
build(,,m2);
for(int i=;i<=n;i++){
ll l=Bin_search(,m2,tmp[i].l);
ll r=Bin_search(,m2,tmp[i].r);
update(,l,r,i);
}
memset(ans,,sizeof(ans));
query(,,m2);
ll cnt=;
for(int i=;i<=m2;i++){
if(ans[i]){
cnt++;
}
}
cout<<cnt<<endl;
}
}
POJ2528 Mayor's posters(线段树染色问题+离散化)的更多相关文章
- POJ2528 Mayor's posters —— 线段树染色 + 离散化
题目链接:https://vjudge.net/problem/POJ-2528 The citizens of Bytetown, AB, could not stand that the cand ...
- POJ2528:Mayor's posters(线段树区间更新+离散化)
Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...
- poj-----(2528)Mayor's posters(线段树区间更新及区间统计+离散化)
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 43507 Accepted: 12693 ...
- [poj2528] Mayor's posters (线段树+离散化)
线段树 + 离散化 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayor ...
- poj2528 Mayor's posters(线段树之成段更新)
Mayor's posters Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 37346Accepted: 10864 Descr ...
- poj2528 Mayor's posters(线段树区间修改+特殊离散化)
Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...
- poj2528 Mayor's posters(线段树区间覆盖)
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 50888 Accepted: 14737 ...
- 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的区间个数,并且最后只是统计能看见的不同 ...
随机推荐
- 【BZOJ3672】【NOI2014】购票(线段树,斜率优化,动态规划)
[BZOJ3672][NOI2014]购票(线段树,斜率优化,动态规划) 题解 首先考虑\(dp\)的方程,设\(f[i]\)表示\(i\)的最优值 很明显的转移\(f[i]=min(f[j]+(de ...
- CentOS6.5上给curl安装ssl时错误解决
1 在CentOS上使用PHP的curl访问HTTPS页面时,出现错误“Protocol https not supported or disabled in libcurl”. 表示curl未启用h ...
- NOIP2015普及组T4推销员(暴力+线段树)
题目:阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第i家住户到入口的距离为Si米.由于同一栋房子里 ...
- 简单shell 编程
简单shell编程 by dreamboy #!/bin/bash while true do echo clear echo echo " 系统维护菜单 " echo &qu ...
- ZABBIX 3.0 配置监控MYSQL性能【OK】
Zabbix3.0自带了MySQL插件来监控mysql数据库的模板,只需要配置好agent客户端,然后在web端给主机增加模板就行了. 参考:http://www.cnblogs.com/keving ...
- [应用篇]第四篇 JSTL之C标签介绍
JSTL 核心标签库标签共有13个,功能上分为4类: 1.表达式控制标签:out.set.remove.catch 2.流程控制标签:if.choose.when.otherwise 3.循环标签:f ...
- 目前最快速的多线程Kmeans算法,java实现
目前最快速Kmeans算法,并由java实现!面对很大的K值表现依然很好. 代码地址: https://github.com/Jethu1/fastKmeans #1.这是一个由java实现的的,多线 ...
- spring boot 2.0.3+spring cloud (Finchley)4、熔断器Hystrix
在分布式系统中服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于他们的其他服务出现远程调度的线程阻塞.某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果 ...
- HDU 4704 欧拉定理
题目看了很久没看懂 就是给你数n,一种函数S(k),S(k)代表把数n拆成k个数的不同方案数,注意如n=3,S(2)是算2种的,最后让你求S(1~n)的和模1e9+7,n<=1e100000.那 ...
- JAVA多线程基础学习二:synchronized
本篇主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题,没错就是使用synchronized. 一.如何解决线程安全问题? 一般 ...