C++数星星(树状数组)

天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。
如果一个星星的左下方(包含正左和正下)有 k
颗星星,就说这颗星星是 k级的。
在这里插入图片描述

例如,上图中星星 是 3 级的(1,2,4 在它左下),星星 2,4 是 1级的。
例图中有 1个 0 级,2 个 1 级,1 个 2 级,1 个 3级的星星。
给定星星的位置,输出各级星星的数目。换句话说,给定 N个点,定义每个点的等级是在该点左下方(含正左、正下)的点的数目,试统计每个等级有多少个点。
输入格式
第一行一个整数 N,表示星星的数目;接下来 N行给出每颗星星的坐标,坐标用两个整数 x,y表示;不会有星星重叠。星星按 y坐标增序给出,y 坐标相同的按 x坐标增序给出。
输出格式
N行,每行一个整数,分别是 0 级,1 级,2 级,……,N−1级的星星的数目。
数据范围
1≤N≤15000,0≤x,y≤32000
输入样例:
5
1 1
5 1
7 1
3 3
5 5
输出样例:
1
2
1
1
0

读题知每个星星左下方的星星数据一定先于这颗星星给出,可以每读一颗星星就算这颗星星的级数,这样将一层一层地从下往上、从左往右计算每颗星星的级数,这颗星星的级数即除它自己以外的以x为坐标的前缀和,故要先查询前缀和再添加这颗星星的数据。显然这是一个动态维护前缀和问题,可以用树状数组。

AC代码:

#include<stdio.h>

const int X=32010;
const int N=15010;

int level[N],tr[X];

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

void add(int x)//在x的位置加1
{
    for(int i=x;i<X;i+=lowbit(i)) ++tr[i];
}

int query(int x)//查询从第1项到第x项的加和
{
    int sum=0;
    for(int i=x;i>0;i-=lowbit(i)) sum+=tr[i];
    return sum;
}

int main()
{
    int n;
    scanf("%d",&n);
    int x,y;
    for(int i=0;i<n;++i)
    {
        scanf("%d%d",&x,&y);
        ++x;//树状数组从1开始计数
        ++level[query(x)];
        add(x);
    }
    for(int i=0;i<n;++i) printf("%d\n",level[i]);
    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
线段树和树状数组都是用来解决区间相关问题的数据结构。 线段树是一种二叉树形式的数据结构,用于解决区间查询问题。每个节点表示一个区间,根节点表示整个区间,通过对区间进适当的划分,将原问题划分为子问题,递归地构建线段树。线段树的叶子节点表示原始数组的单个元素,而其他节点表示其子区间的一些统计信息,如和、最大值、最小值等。通过适当的操作,可以在O(logN)的时间内查询区间的统计信息,也可以在O(logN)的时间内更新一个元素或一个区间的值。 树状数组是一种实现类似累加的数据结构,用于解决前缀查询问题。树状数组的底层数据结构是一个数组,通过对数组的某些位置进增加或查询操作,可以在O(logN)的时间内得到累加值。数组的索引和实际数值之间存在一种特殊的关系,即某个位置的累加值等于该位置的二进制表示中最低位的连续1的个数树状数组的区间查询通过将原始数组转换为差分数组来实现,将查询问题转换为若干个单点查询。 线段树和树状数组在解决问题时都具有一些特定的优势和适用场景。线段树适用于一些需要频繁修改和查询区间统计信息的问题,如区间最值、区间和等。而树状数组适用于一些需要频繁查询前缀和的问题,如求逆序对的数量或统计小于某个数的元素个数等。根据具体的问题需要,我们可以选择合适的数据结构来解决和优化计算效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赴星辰大海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值