pku2528
//离散化+线段树
(以下转)感谢它帮助我理解离散化
假如不离散化,那线段树的上界是10^7,假如建一个那么大的线段树的话。。。必然MLE。于是要考虑离散化。
离散化的目的就是要将线段的长度适当的缩小,但不破坏题意。
比如:
------ (1,6)
------------ (1,12 )
像这样这样的两条线段,可以把它们看作:
-- (1,2)
--- ( 1,3 )
这样,缩短了线段的长度,但是他们的覆盖关系并没有改变。
关键我们要重新给压缩后的线段标记起点和终点。
按照通用的离散化方法。。。。
首先依次读入线段端点坐标,存于post[MAXN][2]中,post[i][0]存第一条线段的起点,post[i][1]存第一条线段的终点,然后用一个结构题数组line[MAXN]记录信息,hash[i].v记录端点坐标,hash[i].line记录这个点属于哪条线段(用正负数表示,负数表示起点,正数表示终点)。假如有N条线段,就有2*N个端点。然后将hash数组排序,按照端点的坐标,从小到大排。接着要把线段赋予新的端点坐标了。从左到右按照递增的次序,依次更新端点,假如2*N个点中,共有M个不同坐标的点,那么线段树的范围就是[1,M]。
1
#include
<
iostream
>
2
#include
<
stdlib.h
>
3
#define
MAXN 10000
4
#define
MAX_UNSIGEN 65536
5
#define
mixcolor -1
6
using
namespace
std;
7
struct
seg
8
{
9
int left,right;
10
int color;
11
}
;
12
struct
structx
13
{
14
int v; //端点值
15
int line; //属于哪条线段,-起,+终
16
}
;
17
18
seg Segtree[MAX_UNSIGEN
+
2
];
//
数
19
bool
colortable[MAXN
+
1
];
20
int
post[MAXN][
2
];
//
记录输入的poster位置,post[i][0]起点,post[i][0]终点
21
structx hash[
2
*
MAXN
+
1
];
//
所有端点,对其排序,相当于一个映射表
22
23
void
buildsegtree(
int
v,
int
l,
int
r)
24
{
25
26
Segtree[v].left=l;
27
Segtree[v].right=r;
28
Segtree[v].color=0;
29
if(l==r) return ;
30
31
int mid=(l+r)>>1; // div 2
32
buildsegtree(v*2,l,mid);
33
buildsegtree(v*2+1,mid+1,r);
34
}
35
36
void
insertseg(
int
v,
int
l,
int
r,
int
c)
37
{
38
if(Segtree[v].left==l && Segtree[v].right==r)
39
{
40
Segtree[v].color=c;
41
return ;
42
}
43
//only one color
44
if(Segtree[v].color != mixcolor )
45
{
46
Segtree[2*v].color=Segtree[v].color;
47
Segtree[2*v+1].color=Segtree[v].color;
48
Segtree[v].color=mixcolor;
49
}
50
51
int mid=(Segtree[v].left + Segtree[v].right) >> 1 ;
52
53
if(r<=mid) insertseg(2*v,l,r,c);
54
else
55
if(mid<l) insertseg(2*v+1,l,r,c);
56
else
57
{
58
insertseg(2*v,l,mid,c);
59
insertseg(2*v+1,mid+1,r,c);
60
}
61
}
62
63
void
count(
int
v ,
int
l,
int
r)
64
{
65
if(Segtree[v].color !=mixcolor )
66
{
67
colortable[Segtree[v].color]=true;
68
return ;
69
}
70
int mid=(Segtree[v].left + Segtree[v].right) >> 1;
71
if(r<=mid) count(2*v,l,r);
72
else if(mid<l) count(2*v+1,l,r);
73
else
74
{
75
count(2*v,l,mid);
76
count(2*v+1,mid+1,r);
77
}
78
}
79
80
int
cmp(
const
void
*
a,
const
void
*
b)
81
{
82
return ((structx*)a)->v - ((structx*)b)->v;
83
}
84
85
int
main()
86
{
87
int c,n,i,j,cnt,index;
88
scanf("%d",&c);
89
while(c--)
90
{
91
scanf("%d",&n);
92
93
for(i=0,j=0,index=1;i<n;i++)
94
{
95
scanf("%d%d",&post[i][0],&post[i][1]);
96
hash[j].v=post[i][0];hash[j++].line=-index;
97
hash[j].v=post[i][1];hash[j++].line=index++;
98
}
99
//j==2*n
100
//离散化
101
qsort(hash,j,sizeof(hash[0]),cmp);
102
post[-hash[0].line-1][0]=1;
103
for(i=1,index=1;i<j;i++)
104
{
105
if(hash[i].v!=hash[i-1].v) index++;
106
107
if(hash[i].line<0)
108
post[-hash[i].line-1][0]=index;
109
else post[hash[i].line-1][1]=index;
110
111
}
112
113
buildsegtree(1,1,index);
114
for(i=0;i<n;i++)
115
insertseg(1,post[i][0],post[i][1],i+1);
116
117
count(1,1,index);
118
cnt=0;
119
for(i=1;i<=MAXN;i++)
120
if(colortable[i]==true)
121
{
122
cnt++;
123
colortable[i]=false;
124
}
125
126
printf("%d\n",cnt);
127
128
}
129
return 0;
130
}
131

2

3

4

5

6

7

8



9

10

11

12

13



14

15

16

17

18

19

20

21

22

23

24



25

26

27

28

29

30

31

32

33

34

35

36

37



38

39



40

41

42

43

44

45



46

47

48

49

50

51

52

53

54

55

56

57



58

59

60

61

62

63

64



65

66



67

68

69

70

71

72

73

74



75

76

77

78

79

80

81



82

83

84

85

86



87

88

89

90



91

92

93

94



95

96

97

98

99

100

101

102

103

104



105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121



122

123

124

125

126

127

128

129

130

131
