Files
python/TangDou/AcWing/BIT/POJ2352.md
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

60 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## [$POJ$ $2352$ $Stars$](http://poj.org/problem?id=2352)
### 一、题目大意
给出$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$的情况,所以整体右移动一位。
### 二、实现代码
```cpp {.line-numbers}
#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;
}
```