题意:有一面墙,然后在上面贴海报,最后看一共能看到几张海报。
思路:本来以为是简单的线段树,但是搞了许久未果。。。 然后上网看了看,才知道这是离散化+hash+线段树
因为题给的,长度的范围比较大,但是给出的海报张数却不是很多。。。
离散化我也是第一次看,我感觉就是把一些数换一种映射方式,但是数据之间的关系(比如:大小)是不变的。
这道题就是把海报的范围,进行排序,去重,映射成了X数组的下标
1 4
2 6
8 10
3 100000
X-- 1 2 3 4 6 8 100000
然后100000就可以映射成6 ,这里还是不明白HH 的线段树中为什么要对相邻之间相差1 的X 进行处理,以后有新的理解的时候,还要再写写。。继续膜拜hh Orz...
比如
1 10
1 3
6 10 这组数据
如果普通的离散化 是 {1,3,6,10} 对应{0,1,2,3}
[0,3]
[0,1] [2,3]
[0,0] [1,1] [2,2] [3,3] 线段树是这样的 那么 1 10 就会被完全覆盖。
所以应该特殊处理 如果相邻数字间距大于1的话 那么就插入一个数,避免这种情况的发生 离散化的结果{1,2,3,4,6,7,10}
如果以后还有新的理解 继续补充!!!
#include<iostream>
#include<algorithm>
using namespace std;
#define lson l , m , rt<<1
#define rson m + 1 , r , rt<<1|1
const int maxn = 10005;
int li[maxn],ri[maxn];
int col[maxn<<4];
bool hash[maxn<<4];
int X[maxn*3];
int cnt;
void PushDown(int rt) {
if (col[rt]!=-1) {
//printf("rt=%d\n",rt);
col[rt<<1] = col[rt<<1|1] = col[rt];
col[rt] = -1;//传递结束记得还原
}
}
void update(int L,int R,int i,int l,int r,int rt) {
if (L <= l&&R >= r) {
col[rt] = i;// 成段更新
return ;
}
PushDown(rt);
int m = (l + r) >> 1;
if (m >= L) update(L , R , i , lson);
if (m < R) update(L , R , i , rson);
}
int Bin(int key,int n,int X[]) {//二分找key 对应的下标m
int l , r;
l = 0 , r = n - 1;
while (l <= r) {
int m = (l + r) >> 1;
if (X[m] == key) return m;
if (key >= X[m]) l = m + 1;
else r = m - 1;
}
return -1;
}
void query(int l,int r,int rt) {//相当于遍历一次线段树吧
if (col[rt] != -1) {//加入hash判断 就能保证用同一种懒惰标记的,也就是颜色相同的区域不用重复判断
if (!hash[col[rt]]) {
//printf("rt==%d\n",rt);
cnt ++;
}
hash[ col[rt] ] = true;
return ;
}
if (l == r) return;
int m = (l + r) >> 1;
query(lson);
query(rson);
}
int main() {
int T , n;
scanf("%d",&T);
while (T --) {
scanf("%d",&n);
int g = 0;
for (int i = 0 ; i < n ; i ++) {
scanf("%d%d",&li[i],&ri[i]);
X[g++] = li[i];
X[g++] = ri[i];
}
sort(X , X + g);
int m = 1;
for (int i = 1 ; i < g ; i ++) {
if (X[i] != X[i-1]){
X[m++] = X[i];
}
}
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);
//printf("l=%d , r=%d\n",l,r);
update(l , r , i , 0 , m , 1);
}
memset(hash,false,sizeof(hash));
cnt = 0;
query(0 , m , 1);
printf("%d\n",cnt);
}
}