• ural(Timus) 1028 Stars


    树状数组

    经典入门题,只要搜索数星星就能在各个OJ找到这个题目,不过不同OJ的输入和输出可能不同,但是题意是一样的,就是统计每个星星的等级

    入门题详细说一下。首先对输入的星星进行排序,先按x坐标升序排序,x坐标相同的按y坐标升序排序,这样做是后面能使用树状数组的根本保证。由于这题,输入数据中就已经保证了是按y坐标升序输入若y坐标相同则按x坐标升序输入,所以不需要排序,注意,两种排序方法是一样的。下面就按本题的来讲

    树状数组中是由原数组变化得到的,a是原数组,c是树状数组,并且数组是从下标1开始的,为什么从1开始是因为位运算和二进制的一些问题。在这里我们已经知道0<=x,y<=32000,所以我们的数组长度就是这么大。为什么呢?因为我们统计的是x的个数

    a[x]表示坐标为x的星星有多少个,所以c[x]就是对应的一段和c[x]=a[x-2^k+1]……a[x]。我们要知道一个星星的等级也就是其左下方有多少个星星,那么我们先知道在其左边有多少个星星,再知道其下面有多少个星星,但是其下面有多少个星星是不用计算的,已经知道了,为什么,因为数据是按照y升序排序的(现在终于知道了为什么要排序了)。那么也就说,对于第i个星星,前面i-1个星星一定在其下方或者同一水平线上(其后面的星星一定在其上方或者同一水平线上,是一定不符合要求的不用考虑)。只要在这些星星中选出一些星星,它们的x比第i个星星的x小,那么就可以计数了。我们初始化话原数组a和树状数组均为0,a[x]表示到目前为止,横坐标为x的星星有多少个,注意这个,到目前为止。所以没读入一个星星,就可以去更新a数组,即对应的a[x]加1,同样的a数组的变化要对应到c数组的变化。只要不断读入星星的坐标,并不断更新c数组就可以了。我们可以发现,a数组只是帮组我们理解,根本不需要用到它,所以是不需要专门开辟一个a数组的


    由于一个星星的等级只和它前面的星星有关,和后面的星星无关,所以我们已经可以一边读入数据一边计算每个星星的等级了!排序保证了y坐标是递增的,我们只要知道横坐标为1到x的星星的个数就是当前星星的等级。

    由于坐标中有0,但是树状数组是 从1开始的,所以对于每个x都要加1后再操作,否则是错误的

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 15010
    #define MAX 32010
    
    int c[MAX],ans[N];
    
    int lowbit(int n)
    { return n&(-n); }
    
    int sum(int p)
    {
        int ans=0;
        while(p)
        {
            ans += c[p];
            p -= lowbit(p);
        }
        return ans;
    }
    
    void add(int p ,int n ,int k)
    {
        while(p<=n)
        {
            c[p] += k;
            p += lowbit(p);
        }
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            memset(c,0,sizeof(c));
            memset(ans,0,sizeof(ans));
    
            for(int i=0; i<n; i++)
            {
                int x,y,level;
                scanf("%d%d",&x,&y);
                level=sum(x+1);
                //printf("level=%d\n",level);
                ans[level]++;
                add(x+1,MAX,1);
            }
    
            for(int i=0; i<n; i++)
                printf("%d\n",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    VS2013编译sqlicipher的.net版本
    oracle 通过obdc sqlserver
    PPT2016输出文件图片的分辨率
    EndNote新参考文献格式下载及使用
    word 利用 ‘邮件合并’提取字段批量生成文案
    matlab 制图——填充两曲线 之间的区域
    Geoda计算莫兰指数
    皮尔逊相关系数计算
    Matlab mat文写入txt
    多元地理加权回归软件使用和含义
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2961290.html
Copyright © 2020-2023  润新知