POJ_2528 Mayor's poster(线段树+离散化)
来源:互联网 发布:世界网络多少年了 编辑:程序博客网 时间:2024/06/06 07:01
题目请点我
题解:
这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷。把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变。
举个例子:
区间:[2,6],[4,8],[6,10]
我们进行下面对应:
2 4 6 8 10
1 2 3 4 5
则原区间变为[1,3],[2,4],[3,5]。可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多。
但是注意对应后,应该有一个去重的操作,防止出错。还有一点去需要注意,区间的对应稍不注意会出现颜色丢失的情况,如下:
[1,10],–[1,4],–[6,10]
当我们手工模拟会发现,我们只是对1,4,6,10,进行了对应,即1,2,3,4,原集合中的4,6被视为了相邻元素,所以5处的颜色丢失,最终得到了错误的结果。
为了防止发生这种情况我们进行插值,在两个不相邻的节点间插入无关值,但是能有效的避免这种情况。数组范围分析,10000个区间对应最多20000个节点,再进行插值后得到最多40000+个节点,对应segTree数组达到4×40000+。
而线段树部分实现起来就比较简单了,lazy标记一下,最后统计仍可见的不同颜色就可以了。
参考博客
代码实现:
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#define MAX 20010#define LCHILD root<<1,l,mid#define RCHILD root<<1|1,mid+1,r#define MID(x,y) (x+y)>>1using namespace std;int T;int N;int mm[MAX<<2];int show[MAX<<3];int L[MAX],R[MAX];int segTree[MAX<<3];void pushdown(int root);int query(int root,int l,int r,int a,int b);void update(int root,int l,int r,int a,int b,int flag);int main(){ scanf("%d",&T); while( T-- ){ scanf("%d",&N); int pos = 1; int tmp = 2; //注意show[0]要提前标记为1 memset(segTree,0,sizeof(segTree)); memset(show,0,sizeof(show));show[0] = 1; for( int i = 1; i <= N; i++ ){ scanf("%d%d",&L[i],&R[i]); mm[pos++] = L[i]; mm[pos++] = R[i]; } //去重操作 sort(mm+1,mm+pos); for( int i = 2; i < pos; i++ ){ if( mm[i] != mm[i-1] ){ mm[tmp++] = mm[i]; } } //插值 pos = tmp; for( int i = pos-1; i > 1; i-- ){ if( mm[i] != mm[i-1]+1 ){ mm[pos++] = mm[i-1]+1; } } sort(mm+1,mm+pos); //lowe_bound找到a,b位置 for( int i = 1; i <= N; i++ ){ int a,b; a = lower_bound(mm+1,mm+pos,L[i])-mm; b = lower_bound(mm+1,mm+pos,R[i])-mm; update(1,1,pos-1,a,b,i); } int res = query(1,1,pos-1,1,pos-1); printf("%d\n",res); } return 0;}void update(int root,int l,int r,int a,int b,int flag){ if( a > r || b < l ){ return ; } if( a <= l && r <= b ){ segTree[root] = flag; return ; } if( segTree[root] != 0 ){ pushdown(root); } int mid = MID(l,r); update(LCHILD,a,b,flag); update(RCHILD,a,b,flag); return ;}int query(int root,int l,int r,int a,int b){ if( a > r || b < l ){ return 0; } //该区间属于同一种颜色,show数组标记是否已被统计 if( segTree[root]!= 0 ){ if( show[segTree[root]] != 1 ){ show[segTree[root]] = 1; return 1; } return 0; } //未标色的叶子节点 if( l == r ){ return 0; } int mid = MID(l,r); return query(LCHILD,a,b)+query(RCHILD,a,b);}void pushdown(int root){ segTree[root<<1] = segTree[root]; segTree[root<<1|1] = segTree[root]; segTree[root] = 0; return ;}
0 0
- POJ_2528 Mayor's poster(线段树+离散化)
- Mayor's posters (poj_2528) 线段树 + 区间离散
- Mayor's posters----POJ_2528----线段树之成段更新and离散化
- poj_2528 Mayor's posters(线段树染色+离散化处理)
- POJ2528 Mayor's poster 线段树+离散化解法
- POJ 2528 Mayor's Poster(还是线段树,外加离散化)
- POJ_2528 线段树+离散化
- 【线段树+离散化】Mayor's Posters
- 线段树+离散化Mayor's posters
- poj 2528 线段树 lazy Mayor's poster
- POJ2528 Mayor's poster 线段树+插入节点建树解法
- POJ2528 Mayor's poster 线段树 插入 查询 删除
- 离散化+线段树 POJ 2528 (Mayor's posters)
- POJ 2528 Mayor's posters(离散化+线段树)
- poj 2528 Mayor's posters 离散化 线段树
- pku 2528 Mayor's posters-线段树+离散化
- POJ 2528 Mayor's posters 线段树+离散化
- poj 2528 Mayor's posters 线段树+离散化
- poj 2242 数学(给三点求外接圆周长)
- 删除Android system目录下文件的方法
- hdoj 2824 The Euler function
- GCD大白话
- Strurts2下导出Excel文件(含下载弹出框)
- POJ_2528 Mayor's poster(线段树+离散化)
- 使用.NET中的XML注释(一) -- XML注释标签讲解
- 没有绝对公正——而是竞争
- [leetcode-222]Count Complete Tree Nodes(c)
- Torch7 doc
- 插值技术之Catmull-Rom Spline Interpolating(2)
- 百度之星1005 序列变换(lis)
- HDOJ 2068 RPG的错排(排列组合+错排)
- (待翻译)github入门之遇到SSH Permission Denied问题的原因和解决