//线段树的建树过程主要有两种形式,一种形式是
// [1,3]
// [1,2] [2,3]
//另外一种形式是
// [1,3]
// [1,2] [3,3]
// [1,1] [2,2]
//本文用的是第二种形式,因为有【1,1】这种形式的存在
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
int c,n,left,right;
int i,j;
struct Node
{
int left,right;
int cover;
};
//存储线段树
Node tree[20005*4];
int reg[20005][2];
int dis[10000005];
int ep[20005];
int flag[10005];
//创建线段树
void build(int root,int l,int r){
tree[root].left=l;
tree[root].right=r;
tree[root].cover=0;
if(l==r)
return;
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
}
//向线段树中插入区间(a,b)
void insert(int root,int a,int b,int col){
if(b<tree[root].left||a>tree[root].right)
return;
if(a<=tree[root].left && b>=tree[root].right){
tree[root].cover=col;
return;
}
if(tree[root].cover>=0){
tree[root*2].cover=tree[root*2+1].cover=tree[root].cover;
tree[root].cover=-1;
}
insert(root*2,a,b,col);
insert(root*2+1,a,b,col);
}
void Count(int root,int l,int r){
if(tree[root].cover>=0) flag[tree[root].cover]=1;
else if(r-l>=1){
Count(root*2,l,(l+r)>>1);
Count(root*2+1,(l+r)>>1+1,r);
}
}
int main(){
scanf("%d",&c);
while(c--){
memset(dis,0,sizeof(dis));
memset(flag,0,sizeof(flag));
scanf("%d",&n);
int p=0;
for(i=1;i<=n;i++){
scanf("%d%d",®[i][0],®[i][1]);
if(dis[reg[i][0]]==0){
//设置为访问过,这个过程是为了去重
dis[reg[i][0]]=1;
ep[++p]=reg[i][0];
}
if(dis[reg[i][1]]==0){
dis[reg[i][1]]=1;
ep[++p]=reg[i][1];
}
}
//离散化
sort(ep+1,ep+1+p);
int hash=0;
for(i=1;i<=p;i++){
dis[ep[i]]=++hash;
}
//创建线段树
build(1,1,p);
for(i=1;i<=n;i++){
insert(1,dis[reg[i][0]],dis[reg[i][1]],i);
}
Count(1,1,p);
int res=0;
for(i=0;i<=n;i++)
if(flag[i])
res++;
if(flag[0])
printf("%d\n",res-1);
else
printf("%d\n",res);
}
return 0;
}
POJ 2528 线段树+离散化
最新推荐文章于 2019-07-31 23:25:00 发布