您的位置:首页 > 其它

poj2352_线段树

2013-05-02 10:27 176 查看
题目描述:

  
给出一个根据星星所处坐标位置来计算星星等级的规则。求位于每个等级的星星的个数。

 

解题思路:

  
思路一:不用线段树的话,就是直接计算x坐标序列的序号:即遍历x,计算当前x之前有几个数小于等于自己(二分找),记为当前数所处的level。最后统计一下即可。这个是个线性的查找法,所以复杂度是n平方。

  
思路二:用线段树的话,基本思路就是把建立区间树,然后计算的等级等于遍历x序列,修改标签值时累加的左子树的标签和。re了几次,需要注意:线段树不是完全二叉树!比如某个线段树的左子树是[1-7],还有右子树,所以你就能看到左子树的7这个点是没有孩子的,不是完全二叉树。数组大小一定要开够。

 

代码:

线段树——:

#include <stdio.h>

#include <stdlib.h>

#define N 15010

#define TREENUM 32010

typedef struct{

   int l, r;

   int tab;

}CH;

CH segTree[3*TREENUM]; //不是完全二叉树!

int n, min = 32001, max=0,
level[N+1],cntLevel[N+1],pos,y,x[N+1];

void buildTree(int index, int l, int r){

   CH ch;

   ch.l = l;

   ch.r = r;

   ch.tab = 0;

   segTree[index] = ch;

   if( l == r )

      
;

   else{

      
buildTree(2*index, l,(l+r)/2);

      
buildTree(2*index+1, (l+r)/2+1, r);

   }

}

void mark(int num, int index ){

   segTree[index].tab
++;//沿路打标记,表示点落在该范围

   if( segTree[index].l !=
segTree[index].r){

      
if(num <= (segTree[index].l +
segTree[index].r)/2){

          
mark(num,2*index);

      
}else {

          
level[pos] += segTree[2*index].tab;//计算级别 += 左子树的点数量

          
mark(num,2*index+1);

      
}

   }else{

      
level[pos] += segTree[index].tab - 1;

   }

}

main(){

   int  i;

  
memset(level,0,sizeof(level));

  
memset(cntLevel,0,sizeof(cntLevel));

  
scanf("%d",&n);

  
for(i=1;i<=n;i++){

     
scanf("%d %d",&x[i],&y);

     
if(x[i] < min)

        
min = x[i];

     
if(x[i] > max)

        
max = x[i];

   }

  
for(i=1;i<=n;i++){

     
x[i] -= min;

   }

   // [min, max]

   max = max-min;

   min = 0;

   // build tree of [0,max]

   buildTree(1,min,max); //
2*(max+1) - 1 个节点

   // mark tab in segTree

  
for(pos=1;pos<=n;pos++){

     
mark(x[pos],1);

     
//printf("after mark, segtree's tab is:");

//     
for(i=1;i<=2*max+1;i++)

//        
printf("%d ",segTree[i].tab);

//     
printf("\n");

   }

  
for(i=1;i<=n;i++){

     
cntLevel[level[i]] ++ ;

     
//printf("%d为%d级别\n",x[i],level[i]);

   }

  
for(i=0;i<n;i++)

     
printf("%d\n",cntLevel[i]);

     

  

   //system("pause");

   return 0;

}

非线段树:

#include <stdio.h>

#include <stdlib.h>

#define N 15001

int n,y,x
,level
,tag
, taglen;

int binarySearch(int t){

  

   int low = 0, high = taglen,
mid = (low+high)/2;

  

   while(low <=
high){

     
if( t< tag[mid]){

         
high = mid-1;

     
}else{

        
low = mid + 1;

     
}

     
mid = (low+high)/2;

   }

   return low;

  

}

main(){

   int i,j,pos;

  

  
memset(level,0,sizeof(level));

  
scanf("%d",&n);

  
for(i=1;i<=n;i++){

     
scanf("%d %d",&x[i],&y);

     
tag[i] = 32001;

   }

   tag[0] = 32001;

   //find

   taglen = 0;

  
for(i=1;i<=n;i++){

     
pos = binarySearch(x[i]);

     
//printf("pos=%d\n",pos);

     
//插入pos 起往后移位

     
for(j=taglen-1;j>=pos;j--){

        
tag[j+1] = tag[j];

     
}

     
tag[pos] = x[i];

     
taglen ++;

     
level[pos]++;

   }

  

  
for(i=0;i<n;i++)

     
printf("%d\n",level[i]);

                    

  

   //system("pause");

   return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: