You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2.5 KiB
2.5 KiB
POJ
2352
Stars
一、题目大意
给出n
个点坐标, 按照y
升序的顺序, 若y
相同, 则按照x
升序的顺序. (不用我们自己排序,是y,x
由小到大的顺序给出的坐标)
一个点坐标小于另一个点坐标的含义是, 横纵坐标都不大于另一个点坐标(保证没有两个点坐标完全相同).
对于给出的n
个点中, 定义该点等级为: 小于该点的所有坐标之和. (左下角星星的个数)
问: 对于0 \sim n-1
的所有等级, 输出有多少个点坐标为该等级.
二、解题思路
乍一看好像是二维树状数组,但是本题降低了难度,对于输入是按照:Y
的升序给出坐标,如果Y
相同,则按照X
的升序给出。
注:不是应该声明个结构体,然后让我们排序后再捋着来计算的吗?良心发现吗?还是有什么新的企图??
那么输入第i
颗星星的坐标时,小于等于X[i]
,小于等于Y[i]
,即左下角的星星已经全部出现了,且Y
按照升序给出,因此,可以忽略Y
坐标,只需要找到小于等于X[i]
的星星数量就是星星的级数。
设定数组cnt[x]
,表示X
坐标为x
的星星个数。
找小于等于X[i]
的星星,即找前缀和c[1] \sim c[X[i]]
。
注:题目下标从0
开始,而树状数组不能有下标为0
的情况,所以整体右移动一位。
二、实现代码
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 32010;
int cnt[N];
// 树状数组模板
#define lowbit(x) (x & -x)
typedef long long LL;
int c[N];
void add(int x, int v) {
while (x < N) c[x] += v, x += lowbit(x);
}
LL sum(int x) {
LL res = 0;
while (x) res += c[x], x -= lowbit(x);
return res;
}
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int x, y;
scanf("%d %d", &x, &y); // 这里的y没有用到,想想也是,因为是扫描线是从下向上的,与y的具体值无关
x++; // 树状数组存储从1开始, 所有x映射都+1。
add(x, 1);
// 查询在x之前有多少个数字,也就是有多少个星星个数
cnt[sum(x)]++; // 找到了一个左下角有5个星星的,那么5这个桶计数++,这是题意要求的
}
// 输出所有等级星星的个数
for (int i = 1; i <= n; i++) printf("%d\n", cnt[i]);
return 0;
}