题意:
有n条线段按照顺序进行覆盖,问最后可见的线段有多少。
解题思路:
我们可以对每条线段编号,然后在线段树内定义一个变量c,且c>0时表示当前该结点被第c种线段覆盖,且c==-1表示当前结点被多种线段覆盖,所以在统计时只要判断当前结点的c是否为-1,如果是继续向下访问,如果不是则直接统计。(l,r比价大 注意离散化)
注意:
这里要判断种类有多少,所以要去重。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
using namespace std;
#define MOD 10007
#define MAXN 10011
#define MAXSZ 10000001
#define l1(x) (x<<1)
#define l1p(x) (l1(x)+1)
#define r1(x) ((x)>>1)
struct node{
int L,R,hsL,hsR;
void read(){
scanf("%d%d",&L,&R);
}
};
struct TRnode{
int L,R,c;
};
TRnode TR[(10*MAXN)<<2];
node in[MAXN];
int hash1[MAXN<<3],cnt;
bool vis[MAXN<<3],vis1[MAXN<<3];
void init(){
memset(vis,false,sizeof(vis));
memset(vis1,false,sizeof(vis1));
cnt = 0;
}
void buildTR(int L,int R,int ind){
TR[ind].L = L;
TR[ind].R = R;
TR[ind].c = 0;
if(L==R)return;
int mid = (L+R)>>1;
int tmpind = l1(ind);
buildTR(L,mid,tmpind);
buildTR(mid+1,R,tmpind+1);
}
void pushdown(int ind,int ind1,int ind2){
TR[ind2].c = TR[ind1].c = TR[ind].c;
TR[ind].c = -1;
return;
}
void pushup(int ind,int ind1,int ind2){
if(TR[ind1].c==TR[ind2].c){
if(TR[ind1].c!=-1){
TR[ind].c = TR[ind1].c;
}
}
else {
TR[ind].c = -1;
}
}
void updateTR(int L,int R,int ind,int c){
if(TR[ind].L ==L&&TR[ind].R==R){
TR[ind].c = c;
return;
}
if(TR[ind].c==c){
return;
}
if(TR[ind].L==TR[ind].R)return;
int tmpind = l1(ind);
if(TR[ind].c>=0){
pushdown(ind,tmpind,tmpind+1);
}
int mid = (TR[ind].R+TR[ind].L)>>1;
//updateTR(L,);
if(mid>=R){
updateTR(L,R,tmpind,c);
}
else if(mid<L){
updateTR(L,R,tmpind+1,c);
}
else {
updateTR(L,mid,tmpind,c);
updateTR(mid+1,R,tmpind+1,c);
}
pushup(ind,tmpind,tmpind+1);
}
int Query(int ind){
if(TR[ind].c>=0){
if(TR[ind].c>0&&(!vis1[TR[ind].c])){
vis1[TR[ind].c] = true;
return 1;
}
return 0;
}
if(TR[ind].L==TR[ind].R)return 0;
int tmpind = l1(ind);
return Query(tmpind)+Query(tmpind+1);
}
void prepro(){
sort(hash1,hash1+cnt);
int tmp0 = 1;
for(int i=1;i<cnt;++i){
if(hash1[i]==hash1[i-1])continue;
hash1[tmp0++] = hash1[i];
}
cnt = tmp0;
}
int hashit(int num){
//0x7FFFFFFF
// int ind = (num)*31;
// ind = (ind&0x7FFFFFFF)%MOD;
// if(!ind)ind = 1;
// while(vis[ind]){
// if(hash[ind]==num)return ind;
// ++ind;
// if(ind==MOD){
// ind = 1;
// }
// }
// if(!vis[ind]){
// vis[ind] = true;
// hash[ind] = num;
// }
// return ind;
int L = 0,R=cnt - 1 ,mid;
while(L<R){
mid = r1(L+R);
if(hash1[mid]==num)return mid;
if(hash1[mid]>num){
R = mid;
}
else {
L = mid+1;
}
}
return L;
}
int main(){
//int up = 10007;
// for(int i=2;i<=sqrt(up*1.0);++i){
// if(up%i==0){
// printf("YES\n");
// break;
// }
// }
int c,n;
scanf("%d",&c);
int maxM;
while(c--){
init();
scanf("%d",&n);
//buildTR(1,n,1);
//maxM = n+MOD;
for(int i=0;i<n;++i){
in[i].read();
hash1[cnt++] = in[i].L;
hash1[cnt++] = in[i].R;
//if(map[])
// in[i].hsL = hashit(in[i].L);
// in[i].hsR = hashit(in[i].R);
// while(in[i].hsR<in[i].L){
// in[i].hsR += MOD;
// }
// if(maxM<in[i].hsR){
// maxM = in[i].hsR;
// }
//updateTR(in[i].hsL,in[i].hsR,1,i+1);
}
prepro();
buildTR(1,cnt,1);
for(int i=0;i<n;++i){
in[i].hsL = hashit(in[i].L)+1;
in[i].hsR = hashit(in[i].R)+1;
updateTR(in[i].hsL,in[i].hsR,1,i+1);
}
int ans = Query(1);
printf("%d\n",ans);
}
return 0;
}