poj2528Mayor's posters(线段树加离散化)第一次接触离散化 做的挺辛苦的

http://poj.org/problem?id=2528

线段树加离散化 搜了好多资料 WA了一下午终于把这题做出来了 看讨论上说这题数据有问题 这种离散化严格来说是不对的 但是这题却可以水过去 由于刚接触 就不去探索很精确的离散化的方法了 先把普通的离散化了解下就好

代码

View Code
  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 }

 

posted @ 2012-08-08 16:25  _雨  阅读(172)  评论(0编辑  收藏  举报