POJ 2528 经典!线段树离散化
来源:互联网 发布:淘宝上哪家玉石店靠谱 编辑:程序博客网 时间:2024/06/06 02:34
http://poj.org/problem?id=2528
题意:n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。求出最后还能看见多少张海报。
解法:离散化,如下面的例子(题目的样例),因为单位1是一个单位长度,将下面的
1 2 3 4 6 7 8 10
— — — — — — — —
1 2 3 4 5 6 7 8
离散化 X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] = 8; X[8] = 10
于是将一个很大的区间映射到一个较小的区间之中了,然后再对每一张海报依次更新在宽度为1~8的墙上(用线段树),最后统计不同颜色的段数。
但是只是这样简单的离散化是错误的,
如三张海报为:1~10 1~4 6~10
离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。
新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)
X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10
这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3
最终,1~2为2,3为1,4~5为3,于是输出正确结果3。
我是这样理解这个离散化为啥要加中间一个点:如果贴海报只有两个端点很容易出错,但如果中间有一个点会和两个端点有一样的颜色,统计的时候就不会出错(个人想法!!!)
#include <iostream>#include<algorithm>#include<stdio.h>#include<string.h>using namespace std;const int maxn=10100;#define lson node<<1,l,mid#define rson node<<1|1,mid+1,rint x[maxn<<4];int tree[maxn<<4],ans=0,n=0,num=1;bool hash[maxn<<2];int lx[maxn<<2],rx[maxn<<2];void pushdown(int node){ tree[node<<1]=tree[node<<1|1]=tree[node]; tree[node]=-1;}void update(int node ,int l,int r,int begin, int end,int x){ if(begin<=l&&end>=r) { tree[node]=x; return; } if(tree[node]!=-1) pushdown(node); int mid=(l+r)>>1; if(mid>=begin) update(lson,begin,end,x); if(mid<end) update(rson,begin,end,x);}void query(int node ,int l,int r){ if(l==r) { if(hash[tree[node]]==0) { hash[tree[node]]=1; ans++; } tree[node]=-1; return; } if(tree[node]!= -1) pushdown(node); int mid=(l+r)>>1; query(lson); query(rson);}int bsearch(int ll, int rr,int xx){ int mm; while(ll<=rr) { mm=(ll+rr)>>1; if(x[mm]==xx) return mm; else if(x[mm]>xx) rr=mm-1; else ll=mm+1; } return ll;}int main(){ int T; scanf("%d",&T); while(T--) { memset(tree,-1,sizeof(tree)); memset(hash,0,sizeof(hash)); int cnt=0; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&lx[i],&rx[i]); x[++cnt]=lx[i]; x[++cnt]=rx[i]; } sort(x+1,x+1+cnt); num=1; for(int i=2;i<=cnt;i++) { if(x[i]!=x[i-1]) x[++num]=x[i]; } for(int i=num;i>1;i--) { if(x[i]-x[i-1]>1) x[++num]=x[i]-1; } sort(x+1,x+1+num); for(int i=1;i<=n;i++) { int l=bsearch(1,num,lx[i]); int r=bsearch(1,num,rx[i]); update(1,1,num,l,r,i); } ans=0; query(1,1,num); printf("%d\n",ans); } return 0;}
个人感觉大佬离散化代码实现写的特别棒 orz!!!
还有一个点 : 原来自己写二分的时候条件 写的是 while(l<r) 其实这样会取不到右端点的!!!对二分还是不熟练
- poj 2528--经典线段树+离散化
- POJ 2528 经典!线段树离散化
- poj 2528 线段树+离散化
- POJ 2528 (线段树+离散化)
- poj 2528 (线段树+离散化)
- poj~2528~离散化线段树
- POJ 2528 线段树+离散化
- Poj 2528 线段树+离散化
- 线段树 poj 2528 离散化处理
- poj 2528 线段树 离散化
- POJ 2528 离散化+线段树染色
- poj 2528 坐标离散化+线段树
- POJ 2528 (线段树 离散化)
- POJ 2528 线段树+离散化
- POJ 2528 QAQ线段树+离散化
- poj 2528 离散化+线段树
- POJ 2528 线段树+离散化~
- poj-2528(线段树+离散化)
- 一生只为寻找欢笑——读Linux之父林纳斯自传
- 中国用户体验设计究竟有多强
- 母函数详解(转 侵删)
- ssh框架搭建
- LeetCode刷题(C++)——Remove Duplicates from Sorted List II(Medium)
- POJ 2528 经典!线段树离散化
- CC3220学习笔记---点亮LED PinMux版
- 基于深度学习的图像语义分割技术概述之5.1度量标准
- 双向链表
- python_manual
- I/O流
- JVM对象分代内存划分与垃圾回收
- IntelliJ 创建main函数快捷
- Spring中基于Java的配置@Configuration和@Bean用法