凳子

笔记

scau_数星星(树状数组)

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;
}




阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/christry_stool/article/details/49951227
想对作者说点什么? 我来说一句

树状数组树状数组资料下载

2010年05月03日 411KB 下载

没有更多推荐了,返回首页

不良信息举报

scau_数星星(树状数组)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭