树状数组-Acwing-1265. 数星星

树状数组-Acwing-1265. 数星星

题目:

天空中有一些星星,这些星星都在不同的位置,每个星星有个坐标。

如果一个星星的左下方(包含正左和正下)有 k 颗星星,就说这颗星星是 k 级的。

1.png

例如,上图中星星 5 是 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

题意:

在 平 面 直 角 坐 标 系 中 输 入 N 个 点 的 坐 标 。 规 定 : 某 个 点 的 等 级 l e v e l = 该 点 左 下 方 点 的 个 数 ( 含 正 左 和 正 下 方 的 点 ) 。 在平面直角坐标系中输入N个点的坐标。\\规定:某个点的等级level=该点左下方点的个数(含正左和正下方的点)。 Nlevel=()

输 出 等 级 为 i 的 点 的 数 目 , 0 < = i < = N − 1 。 输出等级为i的点的数目,0<=i<=N-1。 i0<=i<=N1

题解:

坐 标 的 输 入 是 先 按 纵 坐 标 再 按 横 坐 标 升 序 进 行 的 , 现 要 求 在 当 前 点 的 左 下 方 所 有 点 的 数 量 。 事 实 上 , 就 是 先 输 入 的 点 中 横 坐 标 小 于 当 前 点 的 所 有 点 的 数 量 ( 因 为 当 前 点 的 纵 坐 标 必 然 比 先 前 输 入 的 点 要 大 ) 。 坐标的输入是先按纵坐标再按横坐标升序进行的,现要求在当前点的左下方所有点的数量。事实上,\\就是先输入的点中横坐标小于当前点的所有点的数量(因为当前点的纵坐标必然比先前输入的点要大)。 ,()

因 为 横 坐 标 的 值 不 是 始 终 递 增 的 , 那 样 就 需 要 边 修 改 边 求 区 间 和 , 动 态 区 间 求 和 用 树 状 数 组 。 因为横坐标的值不是始终递增的,那样就需要边修改边求区间和,动态区间求和用树状数组。

树 状 数 组 t r [ i ] 维 护 下 标 小 于 等 于 i 的 点 数 量 , 要 求 t r 前 缀 和 即 l e v e l [ i ] 表 示 等 级 为 i 的 点 的 数 量 。 树状数组tr[i]维护下标小于等于i的点数量,要求tr前缀和即level[i]表示等级为i的点的数量。 tr[i]itrlevel[i]i

时 间 复 杂 度 O ( n l o g 2 n ) , n 是 横 坐 标 范 围 。 时间复杂度O(nlog_2n),n是横坐标范围。 O(nlog2n),n

注意:

树 状 数 组 下 标 从 1 开 始 。 树状数组下标从1开始。 1


代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define inf 0x7fffffff
using namespace std;
const int N=32010;
int n;
int tr[N];
int level[N];///节点等级

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

void add(int w,int p)
{
    for(int i=p;i<=N;i+=lowbit(i)) ///N是横坐标上界
        tr[i]+=w;
}

int query(int x)///求左下共有多少节点
{
    int sum=0;
    for(int i=x;i;i-=lowbit(i))
        sum+=tr[i];
    return sum;
}

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x++;///下标从1开始
        level[query(x)]++;///更新节点等级
        add(1,x);///x处的数量增加1
    }

    for(int i=0;i<n;i++) printf("%d\n",level[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值