【题目大意】
在墙上贴海报,问最后能看到几张海报?
【注意点】
1.首先要注意这是段线段树,而非点线段树。读题的时候注意观察图。来看discuss区下面这组数据:
3
5 6
4 5
6 8
上面数据的答案应该是2,注意观察图,覆盖的是区间。
2.离散化
由于覆盖的是区间,不能简单的离散化,否则会出现差错。比如说下面这组数据:
1 5
1 3
4 5
以及
1 5
1 2
4 5
如果简单离散化都会变成:
1 4
1 2
3 4
最后得出只能看到两张海报的结论,而事实上第一组数据中能够看到三张海报,为了解决这个问题,如果相邻两个数之间相差大于1,就补上一个中间的数字。
比如说1 4,离散化成为1 2 3
3.数据范围:线段树要开到<<4,至于为什么还没有研究出来。X要开到三倍,因为不仅要考虑左右边界均放进来,而且还要考虑中间增添上来离散化的数字。
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #define lson l,m,rt<<1
6 #define rson m+1,r,rt<<1|1
7 /*define后面绝对不能加分号*/
8 using namespace std;
9 const int MAXN=10000+50;
10 int l[MAXN],r[MAXN];
11 int X[MAXN*3],t,M;
12 int col[MAXN<<4];
13 int hash[MAXN];
14 /*延迟标记当前区域被编号为几的覆盖*/
15 int ans;
16
17 void pushdown(int rt)
18 {
19 if (col[rt]!=-1)
20 {
21 col[rt<<1]=col[rt];
22 col[rt<<1|1]=col[rt];
23 col[rt]=-1;
24 }
25 }
26
27 int Bin(int key)
28 {
29 int ub=1,lb=M+1;
30 while (lb>ub)
31 {
32 int m=(ub+lb)/2;
33 if (X[m]==key) return m;
34 if (X[m]>key) lb=m;
35 else (ub=m);
36 }
37 return -1;
38 }
39
40 void update(int L,int R,int l,int r,int rt,int cit)
41 {
42 if (L<=l && r<=R)
43 {
44 col[rt]=cit;
45 return;
46 }
47 pushdown(rt);
48 int m=(l+r)>>1;
49 if (L <= m) update(L,R,lson,cit);
50 if (m < R) update(L,R,rson,cit);
51 }
52
53 void query(int l,int r,int rt)
54 {
55 if (col[rt]!=-1)
56 {
57 if (hash[col[rt]]!=1) ans++;
58 hash[col[rt]]=1;
59 return;
60 }
61 if (l==r) return;
62 int m=(l+r)>>1;
63 query(lson);
64 query(rson);
65 }
66
67
68 void init()
69 /*输入数据并进行离散化*/
70 {
71 int num=0;
72 scanf("%d",&t);
73 for (int i=0;i<t;i++)
74 {
75 scanf("%d%d",&l[i],&r[i]);
76 X[++num]=l[i];
77 X[++num]=r[i];
78 }
79 sort(X+1,X+num+1);
80 /*M来记录离散化之后总共出现了几个数字*/
81 M=1;
82 /*注意因为下面的for循环是从2开始的,所以m的初始值要是1,否则第一个数字会被覆盖掉*/
83 for (int i=2;i<=num;i++)
84 {
85 if (X[i]!=X[i-1]) X[++M]=X[i];
86 /*重复的数字只记录一次*/
87 }
88 num=M;
89 for (int i=2;i<=num;i++)
90 {
91 if (X[i]-X[i-1]>1) X[++M]=X[i]-1;
92 /*离散化时要注意,如果两个点相差大于1,则在中间再插入一个数字*/
93 }
94 sort(X+1,X+M+1);
95 }
96
97 void submain()
98 {
99 memset(col,-1,sizeof(col));
100 for (int i=0;i<t;i++)
101 {
102 int lp=Bin(l[i]);
103 int rp=Bin(r[i]);
104 update(lp,rp,1,M,1,i);
105 /*二分查找左边界和右边界离散化后对应的数值*/
106 }
107 }
108
109 int main()
110 {
111 int T;
112 scanf("%d",&T);
113 for (int kase=0;kase<T;kase++)
114 {
115 init();
116 submain();
117 ans=0;
118 memset(hash,0,sizeof(hash));
119 query(1,M,1);
120 cout<<ans<<endl;
121 }
122 return 0;
123 }