POJ 2352 Stars

题目大意:

        天文学家通常在研究星云图时将星星看做平面上的一个点,因此星云图可看做一个平面坐标系,每个星星都有各自的坐标。

        现定义星星的等级,为横纵坐标不大于该星星的星星的数量。

        现给出N(N ≤ 15,000)个星星的位置坐标(坐标数值不大于32,000),按照y坐标从小到大的顺序给出(对于y坐标相同的,按照x坐标从小到大顺序给出),不存在两个坐标完全相同的星星,现在求等级从0-N - 1的星星的数量各为多少。

题目链接

注释代码:

/*            
 * Problem ID : POJ 2352 Stars
 * Author     : Lirx.t.Una            
 * Language   : C      
 * Run Time   : 141 ms            
 * Run Memory : 492 KB            
*/    

#include <stdio.h>
#include <stdlib.h>

//maximum number of stars,星星的最大数量
//15,000 + 1
#define	MAXSTARN		15001
//maximum coordinate,最大原坐标值
//用于原坐标向压缩坐标映射
//因此取32,001可取到数组下标32,000
#define	MAXCORD			32001

int		nlev[MAXSTARN]		= { 0 };//number of level[i],即等级为i的星星的数量
int		bit[MAXSTARN]		= { 0 };//binary indexes tree,树状数组,为x轴的压缩坐标
int		x[MAXSTARN];//存放接受到的星星的x轴坐标,x[i]表示第i个星星的x坐标
int		xtmp[MAXSTARN];//x temp,用于临时保存星星的x轴坐标,经排序后剔除相同的坐标进行压缩
int		xx[MAXCORD];//transformed x aixs,压缩后的x坐标
             //xx[ 原坐标 ] = 压缩后的新的x坐标

int
lowbit(int x) {
	
	return x & ( -x );
}

int
lev(int x) {//level,即树状数组的sum函数,用于求
	//压缩坐标为x的星星的等级
	
	int		sum;
	
	sum = 0;
	while ( x > 0 ) {
		
		sum	+= bit[x];
		x	-= lowbit(x);
	}
	
	return sum;
}

void
add( int x, int max ) {//即树状数组的update函数
	//每计算一个星星的等级后都需要将该星星加入树状数组中
	
	while ( x <= max ) {
		
		bit[x]++;
		x += lowbit(x);
	}
}

int
fcmp(const void *a, const void *b) {
	
	return *(int *)a - *(int *)b;
}

int
main() {
	
	int		n;//星星总数
	int		y;//用于接收星星的y坐标
	int		i, j;//计数变量
	int		ixx;//用于临时存放压缩坐标
	
	scanf("%d", &n);
	for ( i = 1; i <= n; i++ ) {
		
		scanf("%d%d", x + i, &y);
		xtmp[i] = x[i];
	}
	//离散化,压缩映射
	qsort(xtmp + 1, n, sizeof(int), &fcmp);
	for ( i = 1, j = 1; i <= n; i++, j++ ) {
		
		xtmp[j] = xtmp[i];
		xx[ xtmp[j] ] = j;
		
		while ( i < n && xtmp[i] == xtmp[i + 1] )
			i++;
	}
	j--;//j成为压缩坐标的最大坐标了

	//由于输入是按照y升序,并且在相同y中按x升序排列(不存在相同的坐标)
	//因此带插入的星星的y一定大于等于上一个星星的y
	//因此只需要看大于之前星星的x的数量即可
	//所以可以以x坐标作为树状数组的原数组进行构造
	//lev(x)就表示在当前(x, y)插入之前在1-x区间内星星的数量,即当前星星的等级
	for ( i = 1; i <= n; i++ ) {
		
		ixx = xx[ x[i] ];//获得当前星星的x压缩坐标
		nlev[ lev(ixx) ]++;//获取星星的等级后将响应等级的星星数加1
		add( ixx, j );//再将当前星星添加到树状数组中
	}
	
	for ( i = 0; i < n; i++ )
		printf("%d\n", nlev[i]);
	
	return 0;
}

无注释代码:

#include <stdio.h>
#include <stdlib.h>

#define	MAXSTARN		15001
#define	MAXCORD			32001

int		nlev[MAXSTARN]		= { 0 };
int		bit[MAXSTARN]		= { 0 };
int		x[MAXSTARN];
int		xtmp[MAXSTARN];
int		xx[MAXCORD];

int
lowbit(int x) {
	
	return x & ( -x );
}

int
lev(int x) {
	
	int		sum;
	
	sum = 0;
	while ( x > 0 ) {
		
		sum	+= bit[x];
		x	-= lowbit(x);
	}
	
	return sum;
}

void
add( int x, int max ) {
	
	while ( x <= max ) {
		
		bit[x]++;
		x += lowbit(x);
	}
}

int
fcmp(const void *a, const void *b) {
	
	return *(int *)a - *(int *)b;
}

int
main() {
	
	int		n;
	int		y;
	int		i, j;
	int		ixx;
	
	scanf("%d", &n);
	for ( i = 1; i <= n; i++ ) {
		
		scanf("%d%d", x + i, &y);
		xtmp[i] = x[i];
	}
	qsort(xtmp + 1, n, sizeof(int), &fcmp);
	for ( i = 1, j = 1; i <= n; i++, j++ ) {
		
		xtmp[j] = xtmp[i];
		xx[ xtmp[j] ] = j;
		
		while ( i < n && xtmp[i] == xtmp[i + 1] )
			i++;
	}
	j--;
	for ( i = 1; i <= n; i++ ) {
		
		ixx = xx[ x[i] ];
		nlev[ lev(ixx) ]++;
		add( ixx, j );
	}
	
	for ( i = 0; i < n; i++ )
		printf("%d\n", nlev[i]);
	
	return 0;
}

单词解释:

astronomer:n, 天文学家

examine:vt, 检查,考试

plane:n, 平面,飞机

Ural:地名,乌拉尔,前苏联一地区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值