数星星
数星星
天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。
如果一个星星的左下方(包含正左和正下)有 颗星星,就说这颗星星是 级的。
例如,上图中星星 是 级的( 在它左下),星星 是 级的。
例图中有 个 级, 个 级, 个 级, 个 级的星星。
给定星星的位置,输出各级星星的数目。
换句话说,给定 个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。
输入格式
第一行一个整数 ,表示星星的数目;
接下来 行给出每颗星星的坐标,坐标用两个整数 表示;
不会有星星重叠。星星按 坐标增序给出, 坐标相同的按 坐标增序给出。
输出格式
行,每行一个整数,分别是 级, 级, 级,……, 级的星星的数目。
数据范围
,
输入样例:
5 1 1 5 1 7 1 3 3 5 5
输出样例:
1 2 1 1 0
解题思路
因为要求二维的和,发现需要用到二维的数据结构。我们想想能不能转为一维的问题。
由于坐标是按照纵坐标递增的顺序给的,所以当前星星的纵坐标一定是已存在的星星纵坐标最大的那个。当前星星后面的所有星星(也就是还没给出的星星),要么比当前这个星星的横坐标大(在当前星星的右边),要么比当前星星的纵坐标大(在当前星星的上面)。因此当前星星左下方区域的星星一定是以前出现过的星星,后面的星星就不用再考虑了。因此我们只需要从前面的星星看一下哪些星星的横坐标以及纵坐标都小于当前的星星。又因为当前星星的纵坐标是最大的,所以前面所有的星星纵坐标一定小于当前星星的纵坐标,所有只需要统计横坐标小于等于当前星星的星星个数。
假设当前星星的横坐标为,也就是求横坐标在星星的个数。可以发现这是在求一个前缀和。我们用一个数组记录横坐标为的星星的个数,表示横坐标为的星星的个数。要求横坐标不超过星星的个数等价于求。
因为每多一个星星都要对加,因此这是一个动态求前缀和的过程。因此一共有两个操作,一个是给某个坐标加,另一个是求某个区间的前缀和,因此要用到树状数组。
AC代码如下:
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int N = 32e3 + 10; 6 7 int tr[N], level[N]; 8 9 int lowbit(int x) { 10 return x & -x; 11 } 12 13 int query(int x) { 14 int ret = 0; 15 for (int i = x; i; i -= lowbit(i)) { 16 ret += tr[i]; 17 } 18 return ret; 19 } 20 21 void add(int x) { 22 for (int i = x; i < N; i += lowbit(i)) { 23 tr[i]++; 24 } 25 } 26 27 int main() { 28 int n; 29 scanf("%d", &n); 30 for (int i = 0; i < n; i++) { 31 int x, y; 32 scanf("%d %d", &x, &y); 33 x++; 34 level[query(x)]++; // query(x)表示求下标为1~x这个区间的和 35 add(x); // 给下标为横坐标为x的星星数量加1 36 } 37 38 for (int i = 0; i < n; i++) { 39 printf("%d\n", level[i]); 40 } 41 42 return 0; 43 }
参考资料
AcWing 1265. 数星星(蓝桥杯C++ AB组辅导课):https://www.acwing.com/video/670/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/15924485.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效