posts - 100,  comments - 15,  trackbacks - 0
//离散化+线段树

(以下转)感谢它帮助我理解离散化

假如不离散化,那线段树的上界是10^7,假如建一个那么大的线段树的话。。。必然MLE。于是要考虑离散化。
离散化的目的就是要将线段的长度适当的缩小,但不破坏题意。
比如:
------   (1,6)
------------ (1,12 )
像这样这样的两条线段,可以把它们看作:
-- (1,2)
--- ( 1,3 )
这样,缩短了线段的长度,但是他们的覆盖关系并没有改变。
关键我们要重新给压缩后的线段标记起点和终点。
按照通用的离散化方法。。。。
首先依次读入线段端点坐标,存于post[MAXN][2]中,post[i][0]存第一条线段的起点,post[i][1]存第一条线段的终点,然后用一个结构题数组line[MAXN]记录信息,hash[i].v记录端点坐标,hash[i].line记录这个点属于哪条线段(用正负数表示,负数表示起点,正数表示终点)。假如有N条线段,就有2*N个端点。然后将hash数组排序,按照端点的坐标,从小到大排。接着要把线段赋予新的端点坐标了。从左到右按照递增的次序,依次更新端点,假如2*N个点中,共有M个不同坐标的点,那么线段树的范围就是[1,M]。
  1#include<iostream>
  2#include<stdlib.h>
  3#define MAXN 10000
  4#define MAX_UNSIGEN 65536
  5#define mixcolor -1
  6using namespace std;
  7struct seg
  8{
  9    int left,right;
 10    int color;
 11}
;
 12struct structx
 13{
 14    int v;       //端点值
 15    int line;    //属于哪条线段,-起,+终
 16}
;
 17
 18seg Segtree[MAX_UNSIGEN+2];    //
 19bool colortable[MAXN+1];
 20int post[MAXN][2];            //记录输入的poster位置,post[i][0]起点,post[i][0]终点
 21structx hash[2*MAXN+1];        //所有端点,对其排序,相当于一个映射表
 22
 23void buildsegtree(int v,int l,int r)
 24{
 25    
 26    Segtree[v].left=l;
 27    Segtree[v].right=r;
 28    Segtree[v].color=0;
 29    if(l==r) return ; 
 30
 31    int mid=(l+r)>>1// div 2
 32    buildsegtree(v*2,l,mid);
 33    buildsegtree(v*2+1,mid+1,r);
 34}

 35
 36void insertseg(int v,int l,int r,int c)
 37{
 38        if(Segtree[v].left==&& Segtree[v].right==r)
 39        {
 40            Segtree[v].color=c;
 41            return ;
 42        }

 43        //only one color
 44        if(Segtree[v].color != mixcolor )  
 45        {
 46            Segtree[2*v].color=Segtree[v].color;
 47            Segtree[2*v+1].color=Segtree[v].color;
 48            Segtree[v].color=mixcolor;
 49        }

 50        
 51        int mid=(Segtree[v].left + Segtree[v].right) >> 1 ;
 52
 53        if(r<=mid) insertseg(2*v,l,r,c);
 54        else 
 55            if(mid<l) insertseg(2*v+1,l,r,c);
 56        else 
 57        {
 58            insertseg(2*v,l,mid,c);
 59            insertseg(2*v+1,mid+1,r,c);
 60        }

 61}

 62
 63void count(int v ,int l,int r)
 64{
 65    if(Segtree[v].color !=mixcolor ) 
 66    {
 67        colortable[Segtree[v].color]=true;
 68        return ;
 69    }
        
 70    int mid=(Segtree[v].left + Segtree[v].right) >> 1;
 71    if(r<=mid) count(2*v,l,r);
 72    else if(mid<l) count(2*v+1,l,r);
 73        else 
 74        {
 75            count(2*v,l,mid);
 76            count(2*v+1,mid+1,r);
 77        }

 78}

 79
 80int cmp(const void *a,const void *b)
 81{
 82    return ((structx*)a)->- ((structx*)b)->v;
 83}

 84
 85int main()
 86{
 87    int c,n,i,j,cnt,index;    
 88    scanf("%d",&c);
 89    while(c--)
 90    {
 91        scanf("%d",&n);
 92
 93        for(i=0,j=0,index=1;i<n;i++)
 94        {
 95            scanf("%d%d",&post[i][0],&post[i][1]);
 96            hash[j].v=post[i][0];hash[j++].line=-index;
 97            hash[j].v=post[i][1];hash[j++].line=index++;
 98        }

 99        //j==2*n
100        //离散化
101        qsort(hash,j,sizeof(hash[0]),cmp);    
102        post[-hash[0].line-1][0]=1;
103        for(i=1,index=1;i<j;i++)
104        {
105            if(hash[i].v!=hash[i-1].v) index++;
106
107            if(hash[i].line<0)
108                post[-hash[i].line-1][0]=index;
109            else post[hash[i].line-1][1]=index;
110
111        }

112                
113        buildsegtree(1,1,index);
114        for(i=0;i<n;i++)
115            insertseg(1,post[i][0],post[i][1],i+1);
116
117        count(1,1,index);
118        cnt=0;
119        for(i=1;i<=MAXN;i++)
120            if(colortable[i]==true
121            {
122                cnt++;
123                colortable[i]=false;
124            }

125            
126        printf("%d\n",cnt);
127
128    }

129    return 0;
130}

131
posted on 2009-04-17 19:16 wyiu 阅读(265) 评论(0)  编辑 收藏 引用 所属分类: POJ

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理