http://poj.org/problem?id=2528
线段树加离散化 搜了好多资料 WA了一下午终于把这题做出来了 看讨论上说这题数据有问题 这种离散化严格来说是不对的 但是这题却可以水过去 由于刚接触 就不去探索很精确的离散化的方法了 先把普通的离散化了解下就好
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include<cstdio> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 #define N 20000 7 struct node 8 { 9 int li,num;//li记录端点 num记录这是第几个线段 10 }line[N*3]; 11 int s[N*6],po[N][2],num,vi[N]; 12 bool cmpp(struct node a,struct node b)//按端点排序 13 { 14 return a.li<b.li; 15 } 16 void ctree(int l,int r,int w) 17 { 18 if(l==r) 19 { 20 s[w] = 0; 21 return ; 22 } 23 int m = (l+r)/2; 24 ctree(l,m,2*w); 25 ctree(m+1,r,2*w+1); 26 } 27 void add(int a,int b,int l,int r,int w,int p) 28 { 29 if(l==a&&r==b) 30 { 31 s[w] = p; 32 return; 33 } 34 int m = (l+r)/2; 35 if(s[w]>0) 36 { 37 s[2*w] = s[w]; 38 s[2*w+1] = s[w]; 39 s[w] = 0; 40 } 41 if(b<=m) 42 add(a,b,l,m,2*w,p); 43 else 44 if(a>m) 45 add(a,b,m+1,r,2*w+1,p); 46 else 47 { 48 add(a,m,l,m,2*w,p); 49 add(m+1,b,m+1,r,2*w+1,p); 50 } 51 } 52 void search(int w) 53 { 54 if(s[w]>0) 55 { 56 if(!vi[s[w]]) 57 { 58 vi[s[w]] = 1; 59 num++; 60 } 61 return ; 62 } 63 search(2*w); 64 search(2*w+1); 65 } 66 int main() 67 { 68 int i,j,k,n,m,t,a,b; 69 scanf("%d",&t); 70 while(t--) 71 { 72 73 num = 0; 74 memset(vi,0,sizeof(vi)); 75 scanf("%d",&n); 76 for(i = 0; i < n ; i++) 77 { 78 scanf("%d%d",&po[i][0],&po[i][1]); 79 line[2*i].li = po[i][0]; 80 line[2*i].num = -(i+1);//用负数表示左端点 81 line[2*i+1].li = po[i][1]; 82 line[2*i+1].num = i+1; 83 } 84 sort(line,line+2*n ,cmpp); 85 int g = 1,te = line[0].li; 86 for(i = 0; i < 2*n ; i++)//将这些端点映射成小的数 1、2、3。。。。 87 { 88 if(line[i].li!=te) 89 { 90 g++; 91 te = line[i].li; 92 } 93 if(line[i].num<0) 94 po[-line[i].num][0] = g; 95 else 96 po[line[i].num][1] = g; 97 } 98 ctree(1,g,1);//共g个不同的端点 以g建树 99 for(i = 1; i <= n ; i++) 100 add(po[i][0],po[i][1],1,g,1,i);//将映射完的端点添加 101 search(1); 102 printf("%d\n",num); 103 } 104 return 0; 105 }