关闭

scau_数星星(树状数组)

253人阅读 评论(0) 收藏 举报
分类:

1144 数星星
时间限制:564MS  内存限制:65536K
题型: 编程题   语言: G++;GCC
天文学家们喜欢观察星星。它们把每颗星星看成一个点,并把每颗星星左下方(即横坐标和纵坐标都不比它大)的星星颗数作为它的等级值。</span></div>现给出所有星星(星星个数为N)的坐标,计算并输出指定编号的星星的等级。

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



输入格式
第一行为N
后N行为编号为1到N的星星的坐标(坐标用整数)
此后是M
后一行是M个星星的编号
坐标范围0<=x,y<=1000000
N<=100000 M<=1000


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


输入样例

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


输出样例

1
3

这道题让我第一次认识了树状数组,树状数组能有效解决修改某点的值,或求某区间的和。树状数组其实就是巧妙的利用了二分,使用的是lowbit函数。lowbit(k)就是把k的二进制的高位1全部清空,只留下最低位的1。比较普遍的方法是lowbit(k)=k&-k;这是一种位运算。
接下来我们需要写出维护树的代码update()和求和代码Sum();

至于这道题咱们还需要排序,让它变一维。
给出代码留念

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;

int c[1000001],maxx,cnt[1000001];

struct POI
{
    int x,y,z;
}poi[1000001];

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

int Sum(int n)
{
    int sum=0;
    while(n>0)
    {
        sum+=c[n];
        n-=(n&(-n));
    }
    return sum;
}

void update(int i,int x)
{
    while(i<=maxx)
    {
        c[i]=c[i]+x;
        i+=(i&(-i));
    }
}


int main()
{
    int i,N,M,num;
    memset(c,0,sizeof(c));
    maxx=0;
    scanf("%d",&N);
    for(i=0;i<N;i++)
    {
        scanf("%d%d",&poi[i].x,&poi[i].y);
        poi[i].x++;
        poi[i].y++;
        poi[i].z=i;
        if(maxx<poi[i].x)
        {
            maxx=poi[i].x;
        }
    }
    sort(poi,poi+N,cmp);
    for(i=0;i<N;i++)
    {
        cnt[poi[i].z]=Sum(poi[i].x);

        update(poi[i].x,1);
    }

    scanf("%d",&M);
    int s[M];
    for(i=0;i<M;i++)
    {
        scanf("%d",&num);
        printf("%d\n",cnt[num-1]);
    }
    return 0;
}




0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:32632次
    • 积分:2729
    • 等级:
    • 排名:第14066名
    • 原创:253篇
    • 转载:3篇
    • 译文:0篇
    • 评论:3条
    最新评论