#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 10010
struct node
{
int x1,x2;
}s[N];
int vis[N],st[2*N],str[4*N],ys,count;
struct node1
{
int l,r;
int cp;//标记该节点是否被某张海报完全覆盖
}tree[16*N];//在添加顶点之后,最坏情况下,顶点数会达到4*N
int cmp(const void *a,const void *b)
{
return *(int *)a - *(int *)b;
}
int find(int x)
{
//必须找得到
int mid,l,r;
l=1;
r=ys;
while(r>=l)//向中间逼近
{
mid=(l+r)/2;
if(str[mid]>x) r=mid-1;
else if(str[mid]<x) l=mid+1;
else return mid;
}
}
void bulid(int l,int r,int t)//普通建树
{
int mid;
tree[t].l=l;
tree[t].r=r;
tree[t].cp=0;
if(l==r) return;
mid=(l+r)/2;
bulid(l,mid,2*t);
bulid(mid+1,r,2*t+1);
}
void updata(int l,int r,int t,int num)
{
if(tree[t].l==l && tree[t].r==r)
{
tree[t].cp=num;//颜色覆盖
return;
}
if(tree[t].cp!=0)//已覆盖
{
tree[2*t].cp=tree[2*t+1].cp=tree[t].cp;//颜色向下传 ,不过这一步又是为什么
tree[t].cp=0;
}
if(r<=tree[2*t].r) updata(l,r,2*t,num);
else if(l>=tree[2*t+1].l) updata(l,r,2*t+1,num);
else
{
updata(l,tree[2*t].r,2*t,num);
updata(tree[2*t+1].l,r,2*t+1,num);
}
}
void query(int t)
{
if(tree[t].cp!=0) //已覆盖,未访问
{
if(vis[tree[t].cp]==0)
{
count++;//计算几种颜色
vis[tree[t].cp]=1;//这种颜色已经算过了
}
return;
}
if(tree[t].l==tree[t].r) return;//不断查询
query(2*t);
query(2*t+1);
}
int main()
{
int i,n,ncase,k,ans1,ans2;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d",&n);
k=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&s[i].x1,&s[i].x2);
k++;
st[k]=s[i].x1;
k++;
st[k]=s[i].x2;
}
qsort(st+1,k,sizeof(st[1]),cmp);//比较k次,k为点数 ,把所有的点排序
ys=1;//1 待排序数组首地址2 数组中待排序元素数量3 各元素的占用空间大小4 指向函数的指针,用于确定排序的顺序
str[1]=st[1];
for(i=2;i<=k;i++)//n条边,k个点
{
if(st[i]!=st[i-1])//点不相重
{
if(st[i]!=st[i-1]+1) //如果不是我要改一下
{
ys++;
str[ys]=st[i-1]+1;
}
ys++;
str[ys]=st[i];//如果是的话就直接等下去好了 ,str存离散化后的点
}
}//增加顶点,并除去相等的顶点。
printf("%d\n",ys);
bulid(1,ys,1);//对这些点建树,ys为1-ys建树,即点数
for(i=1;i<=n;i++)//其实这算是初始化 ,回去找点
{
ans1=find(s[i].x1);
ans2=find(s[i].x2);//二分找到边界
printf("%d %d\n",ans1,ans2);
updata(ans1,ans2,1,i);
}
memset(vis,0,sizeof(vis));//初始化
count=0;
query(1);//遍历一次,查询
printf("%d\n",count);//输出
}
return 0;
}
09-17
09-17