题目描述:
给出一个根据星星所处坐标位置来计算星星等级的规则。求位于每个等级的星星的个数。
解题思路:
思路一:不用线段树的话,就是直接计算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;
}