poj2352_线段树

来源:互联网 发布:安尼威尔监控app软件 编辑:程序博客网 时间:2024/06/05 05:23

题目描述:

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

 

解题思路:

  思路一:不用线段树的话,就是直接计算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[N],level[N],tag[N], 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;
}

原创粉丝点击