POJ 2352 Stars

POJ 2352 Stars

一、题目大意

给出n个点坐标, 按照y升序的顺序, 若y相同, 则按照x升序的顺序. (不用我们自己排序,是y,x由小到大的顺序给出的坐标)
一个点坐标小于另一个点坐标的含义是, 横纵坐标都不大于另一个点坐标(保证没有两个点坐标完全相同).
对于给出的n个点中, 定义该点等级为: 小于该点的所有坐标之和. (左下角星星的个数)
问: 对于0n1的所有等级, 输出有多少个点坐标为该等级.

二、解题思路

乍一看好像是二维树状数组,但是本题降低了难度,对于输入是按照:Y的升序给出坐标,如果Y相同,则按照X的升序给出。

:不是应该声明个结构体,然后让我们排序后再捋着来计算的吗?良心发现吗?还是有什么新的企图??

那么输入第i颗星星的坐标时,小于等于X[i],小于等于Y[i],即左下角的星星已经全部出现了,且Y按照升序给出,因此,可以忽略Y坐标,只需要找到小于等于X[i]的星星数量就是星星的级数。

设定数组cnt[x],表示X坐标为x的星星个数。
找小于等于X[i]的星星,即找前缀和c[1]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;
}

posted @   糖豆爸爸  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2020-05-04 Windows下使用SSH密钥实现免密登陆Linux服务器
2013-05-04 我们项目中需要准备的技术
2013-05-04 window 2003 实现多用户远程登录
2013-05-04 XSS的知识普及和预防办法
2013-05-04 免积分下载CSDN软件和新浪资料
Live2D
点击右上角即可分享
微信分享提示