对于区间特别大的 (1~1e7)
但是覆盖次数又特别小的
我们采用离散化..
如样列:
1 4
2 6
8 10
3 4
7 10
把每对拆开 升序排序 去重 得:
1 2 3 4 6 7 8 10
对应序号
1 2 3 4 5 6 7 8
把区间关系用序号的关系来替代:
1 4
2 5
7 8
3 4
6 8
这样 区间是不是就被压缩了呢?
标记:
每个节点有三种值 >0 ==-1 ==0
==0:未被染色 >0:染单色 ==-1:染复色
更新时 不包含:结束 完全包含:直接染色 >=0 改节点为-1并将原色向下推
询问时 遇到==0返回 >0 记录 返回,
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define gl l,(l+r)>>1,num<<1
#define gr ((l+r)>>1)+1,r,num<<1|1
const int MAXN = 20005;
using namespace std;
int pa[10005][2],save[MAXN];
short dis[10000005];
bool tag[10005];
short st[10005<<4];
void insert(int v,int a,int b,int l,int r,int num)
{
if(b<l||a>r)
return;
if(a<=l&&b>=r)
{
st[num]=v;
return;
}
if(st[num]>=0)
{
st[num<<1]=st[num];
st[num<<1|1]=st[num];
st[num]=-1;
}
insert(v,a,b,gl);
insert(v,a,b,gr);
}
int cnt=0;
void calc(int l,int r,int num)
{
if(!st[num])return;
if(st[num]>0)
{
if(!tag[st[num]]) cnt++,tag[st[num]]=1;
return;
}
calc(gl);
calc(gr);
}
int main()
{
//freopen("a.in","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
memset(dis,0,sizeof(dis));
memset(st,0,sizeof(st));
int num=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&pa[i][0],&pa[i][1]);
if(!dis[pa[i][0]])
save[num++]=pa[i][0];
if(!dis[pa[i][1]])
save[num++]=pa[i][1];
dis[pa[i][0]]++;
dis[pa[i][1]]++;
}
sort(save,save+num);
int hash=0;
for(int i=0;i<num;i++)
dis[save[i]]=(++hash);
for(int i=0;i<n;i++)
{
pa[i][0]=dis[pa[i][0]];
pa[i][1]=dis[pa[i][1]];
insert(i+1,pa[i][0],pa[i][1],1,hash,1);
}
cnt=0;
memset(tag,0,sizeof(tag));
calc(1,hash,1);
printf("%d\n",cnt);
}
return 0;
}