1144数星星(树状数组)

1144 数星星

该题有题解

时间限制:564MS  内存限制:65536K
提交次数:193 通过次数:43

题型: 编程题   语言: G++;GCC

Description

天文学家们喜欢观察星星。它们把每颗星星看成一个点,并把每颗星星左下方(即横坐标和纵坐标都不比它大)的星星颗数作为它的等级值。
现给出所有星星(星星个数为N)的坐标,计算并输出指定编号的星星的等级。

注意:不存在相同坐标的星星



输入格式

第一行为N
后N行为编号为1到N的星星的坐标(坐标用整数)
此后是M
后一行是M个星星的编号

N<=100000
M<=1000

坐标范围0<=x,y<=1000000


输出格式

要求依次输出这M个星星的等级,一行一个


输入样例

5
0 0
2 0
3 0
1 1
2 2
2
4 5


输出样例

1
3


该题为poj上star的变形,也没变多少。求一个星星的等级,也就是求该星星的下面和左面一共有多少个星星。可以现将所有星星的按坐标排序,按y轴先排或者按x轴先排都可以。
若按Y轴排好序后,我们只需要知道该所求星星的左边有多少个星星就行了,也就是有多少个x比它小的。
这样,求之前所有的x,问题就转化为求数列的前缀和,我们可以用树状数组去解决。


下面是一些关于树状数组的博客
http://www.cnblogs.com/huangxincheng/archive/2012/12/05/2802858.html

http://blog.chinaunix.net/uid-22263887-id-1778936.html

http://www.cnblogs.com/zhj5chengfeng/archive/2013/03/20/2965833.html

http://www.cnblogs.com/Hilda/archive/2012/08/08/2628426.html

https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/#prob 

题目代码如下:由于要将星星排序,而排序后又要按原来的下标找到它的位置,可以设置一个结构体
struct bit{
    int x,y,z;
};
x,y存储坐标,而z存储它在原来序列的坐标。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 1000005
using namespace std;



int c[maxn],maxx;

struct BIT{
    int x,y,z;
}bit[maxn];


bool cmp(BIT a, BIT b)
{
    if( a.y == b.y)
        return a.x < b.x;
    return a.y < b.y;
}

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

int sum(int i)
{
    int ans = 0;
    {
        while(i)
        {
            ans += c[i];
            i -= lowbit(i);
        }
    }
    return ans;
}

void update(int i,int newValue)
{
    while(i<=maxx)
    {
        c[i] += newValue;
        i += lowbit(i);
    }
}
int t[maxn], cnt[maxn];
int main()
{
    //freopen("a","r",stdin);
    int n, m;
    memset(c,0,sizeof(c));
    maxx = 0;

    scanf("%d", &n);
    for(int i=0; i<n; i++)
    {
        scanf("%d%d", &bit[i].x,&bit[i].y);
        bit[i].x++;
        bit[i].y++;
        bit[i].z = i;
        if(maxx < bit[i].x)
            maxx = bit[i].x;
    }
    sort(bit,bit+n,cmp);
    for(int i=0; i<n; i++)
    {
        cnt[bit[i].z] = sum(bit[i].x);
        update(bit[i].x,1);
    }
    scanf("%d",&m);
    for(int i=0; i<m; i++)
    {
        scanf("%d", &t[i]);
    }
    for(int i=0; i<m; i++)
    {
        printf("%d\n", cnt[t[i]-1]);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值