题目大意:
天文学家通常在研究星云图时将星星看做平面上的一个点,因此星云图可看做一个平面坐标系,每个星星都有各自的坐标。
现定义星星的等级,为横纵坐标不大于该星星的星星的数量。
现给出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:地名,乌拉尔,前苏联一地区