线段树+离散化 线段树的更新操作相同于涂颜色那题,线段树的查询操作则比涂颜色那题简单,因为查询的是整条线段而不是某一段。 离散化说白了,就是一个排序+二分,也许我的理解还尚不成熟,等以后题目做多了再来讨论 #include<iostream> #include<cstdlib> #include<cstring> using namespace std; #define N 10005 struct node { int l,r,bj,c; }st[8*N]; int ans[N]; struct point { int x,y; }p[N]; int b[N*2]; int cmp(const void *c,const void *d) { return *(int *)c - *(int *)d; } int binsch(int *sou,int key,int n) { int left=1,right=n,mid; while(left<=right) { mid=(left+right)/2; if(sou[mid]==key) return mid; else if(sou[mid]>key) right=mid-1; else left=mid+1; } } void build(int l,int r,int i) { st[i].l=l; st[i].r=r; st[i].bj= i==1?0:-1; st[i].c=0; if(l==r) return; int mid=(l+r)/2; build(l,mid,2*i); build(mid+1,r,2*i+1); } void update(int l,int r,int c,int i) { if(st[i].l>=l&&st[i].r<=r) { st[i].bj=0; st[i].c=c; return ; } if(st[i].bj==0) { st[2*i].bj=st[2*i+1].bj=0; st[2*i].c=st[2*i+1].c=st[i].c; st[i].bj=-1; } int mid=(st[i].l+st[i].r)/2; if(l<=mid) update(l,r,c,2*i); if(r>mid) update(l,r,c,2*i+1); } void query(int i) { if(st[i].bj==0) { ans[st[i].c]=1; return ; } else { query(2*i); query(2*i+1); } } int main() { int ca,n,i,len,cnt; scanf("%d",&ca); while(ca--) { scanf("%d",&n); b[0]=0; len=0; for(i=1;i<=n;i++) { scanf("%d%d",&p[i].x,&p[i].y); b[2*i-1]=p[i].x; b[2*i]=p[i].y; } qsort(b+1,2*n,sizeof(b[1]),cmp); for(i=1;i<=2*n;i++) if(b[i]!=b[len]) b[++len]=b[i]; build(1,len,1); for(i=1;i<=n;i++) update(binsch(b,p[i].x,len),binsch(b,p[i].y,len),i,1); memset(ans,0,sizeof(ans)); query(1); cnt=0; for(i=1;i<=n;i++) if(ans[i]==1) cnt++; printf("%d/n",cnt); } return 0; }