poj2352_線段樹

題目描述:

   給出一個根據星星所處座標位置來計算星星等級的規則。求位於每個等級的星星的個數。

 

解題思路:

   思路一:不用線段樹的話,就是直接計算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;
}

發佈了121 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章