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 }

 

你可能感兴趣的:(poj)