Mayor's posters----POJ_2528----线段树之成段更新and离散化
2012-09-28 11:10
567 查看
题目地址:http://poj.org/problem?id=2528
/* Author:Bob Lee 2012.9.28 =========================================================== 题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报 =========================================================== 思路: 线段树 但是这题的数据很大,要用到离散化 通过神牛大傻的博客,学到了一点东西 那就是普通的离散化是有缺陷的,特别是对于这些区间问题 怎样解决这个缺陷,在题目中已经说的很清楚了 解题过程就是,先将数据读进去之后进行离散化 然后对于每一个区间进行更新 每一次更新都有一个自己的颜色标记,就是第几个i 然后用hash来表示这个是否已经出现过,因为题目中说了 有可能一个大的区间会被一个小区间在中间覆盖 只剩下两端 那个两端只能算一次 所以要用到hash 然后每一次遇到新的颜色 总数就++ 最后就求出来总的数量 区间线段树的进阶题,还是比较经典的 */ #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 11111 bool hash[maxn]; int li[maxn],ri[maxn]; //下面的数组大小也有讲究 /* 因为x数组是用来保存每个区间段的,一次就有2个数据 所以至少要开2倍以上 而col一般来说开4倍就够了,这里为什么要开16倍呢 因为你每次读进去的是两个数 所以要多开一点,这个和单点更新有点区别 */ int x[maxn*3]; int col[maxn<<4]; int cnt; void PushDown(int rt) { if(col[rt] != -1) { col[rt<<1] = col[rt<<1|1] = col[rt]; col[rt] = -1; } } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l && r<=R) { col[rt] = c; return; } PushDown(rt); int m = (l+r)>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,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; int m = (l+r)>>1; query(lson); query(rson); } int Bin(int key,int n,int x[]) { int l=0,r=n-1; while(l <= r) { int m = (l+r)>>1; if(x[m] == key) return m; if(x[m] < key) l = m+1; else r = m-1; } return -1; } int main() { int t,n; 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]); x[nn++] = li[i]; x[nn++] = ri[i]; } sort(x,x+nn); int m=1; //去除掉重复的 for(int i=1;i<nn;i++) { if(x[i] != x[i-1]) x[m++] = x[i]; } //这个是为了避免普通离散化的缺陷 /* 给出下面两个简单的例子应该能体现普通离散化的缺陷: 例子一: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],然后再做线段树就好了. */ for(int 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(int i=0;i<n;i++) { int l = Bin(li[i],m,x); int r = Bin(ri[i],m,x); update(l,r,i,0,m,1); } cnt = 0; memset(hash,false,sizeof(hash)); query(0,m,1); printf("%d\n",cnt); } return 0; }
相关文章推荐
- POJ 2528 Mayor's posters 线段树成段更新+离散化
- Poj 2528 Mayor's posters 线段树 离散化 成段更新
- POJ 2528 Mayor's posters 线段树的区间覆盖 离散化
- POJ 2528 Mayor's posters 离散化和线段树题解
- poj 2528 Mayor's posters【离散化+线段树】
- POJ 2528 Mayor's posters 离散化+线段树
- poj 2528 Mayor's posters 【线段树 + 离散化】
- POJ 2528 Mayor's posters (线段树成段更新+离散化)
- poj 2528 Mayor's posters 【线段树 + 离散化】
- POJ 2528 Mayor's posters 离散化+线段树
- POJ 2528 Mayor's posters 线段树和离散化
- POJ-2528-Mayor's posters【线段树 & 离散化】
- POJ 2528 Mayor's posters(离散化+线段树成段更新)
- POJ 2528 Mayor's posters?(线段树成段更新+离散化)
- POJ 2528 Mayor's posters(线段树成段更新+离散化)
- poj 2528 Mayor's posters(线段树,离散化,成段更新染色)
- (重温)poj 2528 Mayor's posters 线段树 染色+离散化
- POJ 2528 Mayor's posters // 线段树 区间更新 离散化
- POJ训练计划2528_Mayor's posters(线段树/成段更新+离散化)
- POJ 2528 Mayor's posters(线段树+离散化)