Sample Input
1
5
1 4
2 6
8 10
3 4
7 10
Sample Output
4
题意:第一行输入几组样例T,第二行输入n次更新,接下来n行输入每次更新的区间,每次更新在区间上覆盖一种新的颜色,求全部更新完毕之后,最外一层能看到的有几种颜色。
思路:令每种颜色对应一个数字,其中数字0表示未被染色或者被多种颜色染色。
注意:由于l,r过大,需要离散化,但是这里不能直接离散化,直接离散化可能会导致答案错误,比如更新区间是[1,10],[1,3],[7,10]离散l化后变成[1,4],[1,2],[3,4],最后看见的颜色变成2种,但实际上应该是3种。所以这里离散化的时候,先将所有点按从小到大排序,如果是相邻的点可以直接离散化,如果前后两个点相差大于1(比如3、7相差4),则在这两个点之间再添加一个点。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define N 10005
using namespace std;
typedef long long ll;
int vis[10005];
struct node{
int l,r;
}p[10005];
struct H{
int val,id,pos;
}h[20010];
struct Tree{
int l,r;
int sum,add,num,maxn,col;//num记录最小值
}tree[160000];
bool cmp(struct H x,struct H y)
{
return x.val<y.val;
}
//col=0表示这个区间内有多个颜色,否则col表示这个区间是哪种颜色
void pushup(int root){//儿子把信息传递给父亲
if(tree[root<<1].col!=tree[root<<1|1].col)
tree[root].col=0;
else
tree[root].col=tree[root<<1].col;
return ;
}
void pushdown(int root){//父亲把自己的信息传给儿子
if(tree[root].l==tree[root].r)return ;
if(tree[root].add==-1)return ;
tree[root<<1].add=tree[root<<1|1].add=tree[root].add;
tree[root<<1].col=tree[root].add;
tree[root<<1|1].col=tree[root].add;
tree[root].add=-1;
return ;
}
//初始化
void build(int l,int r,int root){
tree[root].l=l;
tree[root].r=r;
tree[root].add=-1;
if(l==r){//初始状态都为0
tree[root].col=0;
return;
}
int mid=(l+r)>>1;
build(l,mid,root<<1);//左区间
build(mid+1,r,root<<1|1); //右区间
pushup(root);//把儿子的信息更新到父亲
return;
}
//更新区间
void update(int l,int r,int z,int root){
if(l<=tree[root].l&&tree[root].r<=r){
tree[root].col=z;
tree[root].add=z;//把要更新的内容保存下来,等到要用儿子时 再去更新
return ;
}
pushdown(root);//用父亲的信息更新儿子
int mid=tree[root].l+tree[root].r>>1;
if(r<=mid)update(l,r,z,root<<1);
else if(l>mid)update(l,r,z,root<<1|1);
else {
update(l,mid,z,root<<1);
update(mid+1,r,z,root<<1|1);
}
pushup(root);//更新父亲
return ;
}
//查找区间信息
int query(int l,int r,int root){
if(tree[root].col) //如果col≠0,这个区间只有一种颜色这种颜色可能出现过可能没出现过
{
if(!vis[tree[root].col])
{
vis[tree[root].col]=1;
return 1;
}
return 0;
}
//如果这个点没被染色过
if(l==r)return 0;
//如果这个区间不止一种颜色
pushdown(root);
int mid=tree[root].l+tree[root].r>>1;
if(r<=mid)return query(l,r,root<<1);
else if(l>mid)return query(l,r,root<<1|1);
else return (query(l,mid,root<<1)+query(mid+1,r,root<<1|1));
}
int main(){
int n,k,t;
int Case=1;
char od[50];
scanf("%d",&t);
while(t--){
memset(vis,0,sizeof(vis));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&p[i].l,&p[i].r);
h[i*2].val=p[i].l;
h[i*2].id=i;
h[i*2].pos=0;
h[i*2+1].val=p[i].r;
h[i*2+1].id=i;
h[i*2+1].pos=1;
}
sort(h,h+n*2,cmp);
int now=0;//当前是第几
int last=-1;//前一个数字的大小
for(int i=0;i<2*n;i++)
{
if(h[i].val!=last)
{
if(h[i].val-last==1||now==0) now++;
else now+=2;
if(h[i].pos==0)
p[h[i].id].l=now;
else p[h[i].id].r=now;
}
else
{
if(h[i].pos==0)
p[h[i].id].l=now;
else p[h[i].id].r=now;
}
last=h[i].val;
}
build(1,now,1);
for(int i=0;i<n;i++)
{
update(p[i].l,p[i].r,i+1,1);
}
printf("%d\n",query(1,now,1));
}
return 0;
}