題目描述:
給出一個根據星星所處座標位置來計算星星等級的規則。求位於每個等級的星星的個數。
解題思路:
思路一:不用線段樹的話,就是直接計算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;
}