POJ 2528 & UVA 10587(线段树+离散+区间修改)
来源:互联网 发布:淘宝信用卡手续费2017 编辑:程序博客网 时间:2024/05/16 06:47
题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报。
思路:线段树直接做会TLE+MLE,因此需要离散。所谓离散就是将区段进行压缩,但是又不改变区间的位置关系。
方法就是将区段的端点值去掉相同的进行排序,举个例子:
给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。
现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9
然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 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,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。
而这题的难点在于每个数字其实表示的是一个单位长度(并非一个点),这样普通的离散化会造成许多错误(包括我以前的代码,poj这题数据奇弱)
给出下面两个简单的例子应该能体现普通离散化的缺陷:
例子一:1-10 1-4 5-10
例子二:1-10 1-4 6-10
普通离散化后都变成了[1,4][1,2][3,4]
线段2覆盖了[1,2],线段3覆盖了[3,4],那么线段1是否被完全覆盖掉了呢?
例子一是完全被覆盖掉了,而例子二没有被覆盖为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]
如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了。
#include<cstdio>#include<cstring>#include<algorithm>#define M ((L+R)>>1)#define ls (o<<1)#define rs (o<<1|1)#define lson ls,L,M#define rson rs,M+1,R#define MAXN 10005using namespace std;int Ft[MAXN*2],F[MAXN*3],setv[MAXN*15];//F[]作为最终映射 Ft[]作为临时映射需要处理后放入F[]bool vis[MAXN];int Li[MAXN],Ri[MAXN],n,T,fn;int yl,yr,ans,v;void pushdown(int o,int L,int R) {if(setv[o]>=0) {setv[ls]=setv[rs]=setv[o];setv[o]=-1;}}void update(int o,int L,int R){if(yl<=L && R<=yr) {setv[o]=v;return;}pushdown(o,L,R);if(yl<=M) update(lson);if(M<yr) update(rson);}void query(int o,int L,int R){if(setv[o]>=0){if(!vis[setv[o]]) vis[setv[o]]=1,++ans;return;}if(L==R) return;if(1<=M) query(lson);if(M<fn-1) query(rson);}int main(){scanf("%d",&T);while(T-- && scanf("%d",&n)){int nn=0;for(int i=0;i<n;++i) {scanf("%d%d",&Li[i],&Ri[i]);Ft[nn++]=Li[i];Ft[nn++]=Ri[i];}sort(Ft,Ft+nn);F[1]=Ft[0],fn=2;for(int i=1;i<nn;++i)if(Ft[i]!=Ft[i-1]){if(Ft[i]-Ft[i-1]>1) F[fn++]=Ft[i-1]+1;F[fn++]=Ft[i];}memset(vis,0,sizeof(vis));memset(setv,-1,sizeof(setv));for(v=0;v<n;++v){yl=lower_bound(F+1,F+fn,Li[v])-F,yr=lower_bound(F+1,F+fn,Ri[v])-F;update(1,1,fn-1);}ans=0;query(1,1,fn-1);printf("%d\n",ans);}return 0;}
- POJ 2528 & UVA 10587(线段树+离散+区间修改)
- poj-2528-线段树离散化区间
- POJ-2528 Mayor's posters (离散+线段树 区间修改 区间查询)
- POJ 2528 区间端点离散化,线段树区间更新
- POJ 2528 Mayor's posters(线段树区间修改+离散化)
- POJ 2528 Mayor's posters ( 线段树 : 区间修改 + 离散化 )
- UVA - 11402(线段树+区间离散)
- hiho1079 线段树区间修改离散化
- poj 2528 线段树离散化+区间更新
- poj 2528 Mayor's posters (线段树+区间离散)
- POJ 2528 Mayor's posters 区间离散化线段树
- POJ 2528 【线段树--离散化,区间覆盖】
- poj 2528 线段树数据离散化+区间更新
- poj 2528 Mayor's posters(线段树+区间离散化)
- POJ 2528(线段树 区间更新 离散化)
- POJ 2528-posters(线段树区间染色+离散化)
- POJ-2528Mayor's posters(离散+线段树区间覆盖)
- POJ 2528(线段树,区间覆盖,离散化思想)
- 实用的峰值检测电路实例与分析
- u-boot_smdkv210 分析二:启动代码start.s分析
- ural 1233
- u-boot_smdkv210 分析一:源码目录结构
- Python stat模块
- POJ 2528 & UVA 10587(线段树+离散+区间修改)
- 让程序崩溃的有头绪(Handling unhandled exceptions and signals)
- sd_fusing总结
- linux内核笔记——物理内存管理
- 双缓冲消息队列-减少锁竞争
- UVa10392 Factoring Large Numbers
- 深入理解l内核v4l2框架之video for linux 2
- zoj 3203 - Light Bulb (三分)
- ZOJ_2705_Dividing a Chocolate(递推斐波那契)