HDOJ题目1541 Stars(树状数组单点更新)

来源:互联网 发布:起个网络名字大全女孩 编辑:程序博客网 时间:2024/06/05 07:48

Stars

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5025    Accepted Submission(s): 1982


Problem Description
Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the given star. Astronomers want to know the distribution of the levels of the stars. 



For example, look at the map shown on the figure above. Level of the star number 5 is equal to 3 (it's formed by three stars with a numbers 1, 2 and 4). And the levels of the stars numbered by 2 and 4 are 1. At this map there are only one star of the level 0, two stars of the level 1, one star of the level 2, and one star of the level 3. 

You are to write a program that will count the amounts of the stars of each level on a given map.
 

Input
The first line of the input file contains a number of stars N (1<=N<=15000). The following N lines describe coordinates of stars (two integers X and Y per line separated by a space, 0<=X,Y<=32000). There can be only one star at one point of the plane. Stars are listed in ascending order of Y coordinate. Stars with equal Y coordinates are listed in ascending order of X coordinate.
 

Output
The output should contain N lines, one number per line. The first line contains amount of stars of the level 0, the second does amount of stars of the level 1 and so on, the last line contains amount of stars of the level N-1.
 

Sample Input
51 15 17 13 35 5
 

Sample Output
12110
 

Source
Ural Collegiate Programming Contest 1999
 

Recommend
LL   |   We have carefully selected several similar problems for you:  1394 3450 1542 1255 1540 
 思路:http://blog.csdn.net/ljd4305/article/details/10183285

题意:大概就是计算每颗星星左下边包括了多少颗星星,这个数值就是level。左下边不包括本身,不超过本身的x,y的坐标,可以等于。问每种level有多少颗星星。


这题,一开始想不到怎么用到树状数组,后来看了一下,发现题目给的数据是已经按x,y排好序的。所以我们可以不用管y的值,为什么呢?

我们一个星星一个星星的读取进来它的坐标,因为它先要把y相等的星星全输出完了,而且是按x递增的方式输出的,然后再会增大y,继续读入之后的星星坐标,

所以我们用树状数组最好了,先看一排的星星坐标,也就是先不管y,只看y值相同的星星坐标的x。设a[i]表示x轴坐标为i的点的level,这个level包括了它本身。

因为x是递增输入的,当一个x输入时,它之后的所有星星的level值肯定都要加一,即x和大于它的a[]数组值都要加一,这是肯定的。这点就是树状数组的最基本应用-单点更新。所以横的x轴处理完了。

那么纵的y轴怎么处理呢?

我们发现,当处理完了一排星星坐标时,下次读入的星星坐标肯定是y增大了,x变没变小不一定,而且我们此时的树状数组里已经存下了之前读入进来的星星的坐标了,那么此时我在y增大的情况下,再读入一个星星坐标,那么这个星星的level是不是就刚好等于它之前已经处理过了的所有a[i](i小于等于这个点的x)的值和了,为什么可以等于?因为你现在还没有对这个点的x的值进行单点更新,故它没有包括自己本身这个点,只是包括了y小于自己的y的x和自己相等的a[x]罢了。所以这里的求a[0]+a[1]+.....+a[x]的和刚好又用到的是树状数组的另一个最基本的应用-区间求和。


所以此题是树状数组的基本应用。


注:此题的x坐标可以为0,而树状数组是从1开始的,所以处理的时候对每个x坐标进行加一即可。输出从level=0,开始。

从0开始会死循环
ac代码
#include<stdio.h>#include<string.h>int num[32002],c[32002];int n;int low(int x){return x&(-x);}void update(int x,int num){while(x<=32001){c[x]+=num;x+=low(x);}}int sum(int x){int s=0;while(x>0){s+=c[x];x-=low(x);}return s;}int main(){int i;while(scanf("%d",&n)!=EOF){int x,y;memset(num,0,sizeof(num));memset(c,0,sizeof(c));for(i=0;i<n;i++){scanf("%d%d",&x,&y);num[sum(x+1)]++;update(x+1,1);}for(i=0;i<n;i++){printf("%d\n",num[i]);}}}


0 0
原创粉丝点击