每个数字是一段单位长度,要在排序后的数组中把相距大于1的点之间再加上一个数字,表示断开
给出下面两个简单的例子应该能体现普通离散化的缺陷:
例子一:1-10 1-4 5-10
例子二:1-10 1-4 6-10
普通离散化后都变成了[1,4][1,2][3,4]
线段2覆盖了[1,2],线段3覆盖了[3,4],那么线段1是否被完全覆盖掉了呢?
例子一是完全被覆盖掉了,而例子二没有被覆盖
#include<stdio.h>
#include<string.h>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 100100
int t,n;
bool hash[maxn];//记录每张海报是否漏出来
int li[maxn],ri[maxn];
int x[maxn*3];
int col[maxn<<4];//?
int cnt;
int Bin(int key,int n,int x[]) //二分查找在x中找x[i]的下标
{
int l=0,r=n-1;
while(l<=r)
{
int m=(l+r)>>1;
if(x[m]==key)
return m;
if(x[m]<key)
l=m+1;
else
r=m-1;
}
return -1;
}
void pushDown(int rt)
{
if(col[rt]!=-1)
{
col[rt<<1]=col[rt<<1|1]=col[rt];//pushDown只更新左右孩子,因为下一次update只用到左右孩子,query遇到col[rt]!=-1就返回,所以没更新到底不影响结果
col[rt]=-1;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]=c;
return ;
}
pushDown(rt);
int m=(l+r)>>1;
if(L<=m)
update(L,R,c,lson);
if(m<R)
update(L,R,c,rson);
}
void query(int l,int r,int rt)
{
if(col[rt]!=-1)
{
if(!hash[col[rt]])
cnt++;
hash[col[rt]]=true;
return ;
}
if(l==r)
return;
int m=(l+r)>>1;
query(lson);
query(rson);
}
int main()
{
int i,j,k,l,m;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
k=0;
for(i=0;i<n;i++)
{
scanf("%d %d",&li[i],&ri[i]);
x[k++]=li[i];
x[k++]=ri[i];//k是所有数字的个数
}
sort(x,x+k);
m=1;
for(i=1;i<k;i++)
{
if(x[i]!=x[i-1])
x[m++]=x[i]; //m是不重复数字的个数
} //去重
for(i=m-1;i>0;i--)
{
if(x[i]!=x[i-1]+1)
x[m++] = x[i-1]+1;
}//间隔大于1的两个数再向数组中加中间的一个数
sort(x,x+m);//m是处理后所有数字的个数
memset(col,-1,sizeof(col));
for(i=0;i<n;i++)
{
int l=Bin(li[i],m,x);
int r=Bin(ri[i],m,x);
update(l,r,i,0,m,1);
}
memset(hash,false,sizeof(hash));
cnt=0;
query(0,m,1);
printf("%d\n",cnt);
}
return 0;
}