POJ 2528 Mayor posters 线段树成段更新入门题
2013-08-29 10:32
337 查看
题意: 在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报
思路: 这题数据范围很大,直接搞超时+超内存,需要离散化:
离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了
所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多
而这题的难点在于每个数字其实表示的是一个单位长度(并非一个点),这样普通的离散化会造成许多错误(包括我以前的代码,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],然后再做线段树就好了.
线段树功能:update:成段替换 query:简单hash
注:注意最大节点数变成了n的4倍
思路: 这题数据范围很大,直接搞超时+超内存,需要离散化:
离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012] 我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了
所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多
而这题的难点在于每个数字其实表示的是一个单位长度(并非一个点),这样普通的离散化会造成许多错误(包括我以前的代码,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],然后再做线段树就好了.
线段树功能:update:成段替换 query:简单hash
注:注意最大节点数变成了n的4倍
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 #define mid int m = (l + r)>>1 #define maxn 10001 int col[maxn<<4]; bool hash[maxn<<2]; int ll[maxn],rr[maxn],x[maxn<<2]; int n,cnt; void push_down(int rt) { if(col[rt]!=-1) { col[rt<<1] =col[rt<<1|1]=col[rt]; col[rt]=-1; } } void update(int a, int b, int c, int l, int r, int rt) { if(a <= l && r <= b) { col[rt]=c; return; } push_down(rt); mid; if(a <=m )update(a, b, c, lson); if(b > m )update(a, b, c ,rson); } void query(int l, int r, int rt) { if(col[rt]!=-1) { if(!hash[col[rt]])cnt++; hash[col[rt]]=true; return; } if(l == r)return; mid; query(lson); query(rson); } int find(int a[],int n, int key)//二分查找 { int l=0,r=n-1; while(l <= r) { mid; if(a[m] == key)return m; else if(a[m] < key)l = m + 1; else r = m - 1; } return -1; } int main() { int cas,i; scanf("%d",&cas); while(cas--) { scanf("%d",&n); int nn=0; for(i=0;i<n;i++) { scanf("%d%d",&ll[i],&rr[i]); //离散化 x[nn++]=ll[i]; //离散化 x[nn++]=rr[i]; //离散化 } //离散化 sort(x,x+nn); //离散化 int m = 1; //离散化 for(i=1;i<nn;i++) //离散化 if(x[i]!=x[i-1])x[m++]=x[i]; //离散化 for(i=m-1;i>0;i--) //离散化 if(x[i]!=x[i-1]+1)x[m++]=x[i-1]+1; //离散化 sort(x,x+m); //离散化 memset(col,-1,sizeof(col)); for(i=0;i<n;i++) { int l = find(x, m ,ll[i]); int r = find(x, m ,rr[i]); update(l, r, i, 0, m-1, 1); } cnt=0; memset(hash,false,sizeof(hash)); query(0, m-1, 1); printf("%d\n",cnt); } return 0; }
相关文章推荐
- 线段树 POJ 3468 A Simple Problem with Integers 线段树 成段更新入门
- POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)
- POJ 3667 Hotel 线段树 区间合并 入门题
- HDU1556-Color the ball-线段树成段更新入门题/前缀和
- POJ 2155 Matrix 二维线段树 奇妙的成段更新 单点查询
- POJ训练计划2528_Mayor's posters(线段树/成段更新+离散化)
- poj 3468 A Simple Problem with Integers 线段树成段更新模板
- 线段树成段更新 poj 3325
- poj 2155 二维线段树或树状数组入门
- 线段树之区间求和 POJ 3468 线段树入门
- poj_3468线段树成段更新求区间和
- poj 2528 线段树成段更新+离散化
- poj1436 Horizontally Visible Segments 线段树成段更新
- POJ 3468 A Simple Problem with Integers线段树成段更新
- poj_3468线段树成段更新求区间和
- poj 3468 A Simple Problem with Integers(线段树成段更新,懒惰标记的使用)经典题目
- POJ 3468 A Simple Problem with Integers 线段树成段更新+区间查询
- poj 3468 A Simple Problem with Integers(线段树成段更新,延迟标记,Lazy)
- POJ 2528 线段树成段更新,数据离散化
- POJ - 2777 Count Color(线段树 成段更新 区间查询)