poj 2528 线段树+离散化
转自:http://blog.csdn.net/non_cease/article/details/7383736
题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报
解法:离散化,如下面的例子(题目的样例),因为单位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。
Sample Input
1
5
1 4
2 6
8 10
3 4
7 10
Sample Output
4
有点坑,明天再看一遍
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define lson l , m , rt << 1 6 #define rson m + 1 , r , rt << 1 | 1 7 8 const int maxn = 11111; 9 bool hash[maxn]; 10 int li[maxn] , ri[maxn]; 11 int X[maxn*3]; 12 int col[maxn<<4]; 13 int cnt; 14 15 void PushDown(int rt) { 16 if (col[rt] != -1) { 17 col[rt<<1] = col[rt<<1|1] = col[rt]; 18 col[rt] = -1; 19 } 20 } 21 void update(int L,int R,int c,int l,int r,int rt) { 22 if (L <= l && r <= R) { 23 col[rt] = c; 24 return ; 25 } 26 PushDown(rt); 27 int m = (l + r) >> 1; 28 if (L <= m) update(L , R , c , lson); 29 if (m < R) update(L , R , c , rson); 30 } 31 void query(int l,int r,int rt) { 32 if (col[rt] != -1){ 33 if (!hash[col[rt]]) cnt++; 34 hash[ col[rt] ] = true; 35 return ; 36 } 37 if (l == r) return ; 38 int m = (l + r) >> 1; 39 query(lson); 40 query(rson); 41 } 42 int Bin(int key,int n,int X[]) { 43 int l = 0 , r = n - 1; 44 while (l <= r) { 45 int m = (l + r) >> 1; 46 if (X[m] == key) return m; 47 if (X[m] < key) l = m + 1; 48 else r = m - 1; 49 } 50 return -1; 51 } 52 int main() { 53 int T , n; 54 //freopen("1.in","r",stdin); 55 scanf("%d",&T); 56 int i; 57 while (T --) { 58 scanf("%d",&n); 59 int nn = 0; 60 for (int i = 0 ; i < n ; i ++) { 61 scanf("%d%d",&li[i] , &ri[i]); 62 X[nn++] = li[i]; 63 X[nn++] = ri[i]; 64 } 65 sort(X , X + nn); 66 /*for(i=0;i<nn;i++) printf("%d ",X[i]); 67 printf("\n");*/ 68 int m = 1; 69 for (int i = 1 ; i < nn; i ++) { 70 if (X[i] != X[i-1]) X[m ++] = X[i]; 71 } 72 for (int i = m - 1 ; i > 0 ; i --) { 73 if (X[i] != X[i-1] + 1) X[m ++] = X[i-1] + 1; 74 } 75 sort(X , X + m); 76 /*for(i=0;i<m;i++) printf("%d ",X[i]); 77 printf("\n");*/ 78 memset(col , -1 , sizeof(col)); 79 for (int i = 0 ; i < n ; i ++) { 80 int l = Bin(li[i] , m , X); 81 int r = Bin(ri[i] , m , X); 82 update(l , r , i , 0 , m , 1); 83 } 84 cnt = 0; 85 memset(hash , false , sizeof(hash)); 86 query(0 , m , 1); 87 printf("%d\n",cnt); 88 } 89 return 0; 90 }