现在的位置: 首页 > 综合 > 正文

poj 2352 Stars

2013年10月05日 ⁄ 综合 ⁄ 共 1367字 ⁄ 字号 评论关闭

http://blog.csdn.net/niushuai666/article/details/7389273

题目链接:http://poj.org/problem?id=2352

题目大意:

给你星星的坐标(y递增,若y相等,x递增),每个星星都有一个等级,规定它的等级就是在它左下方的星星的个数。输入所有星星后,依次输出等级为0到n-1的星星的个数。

解题思路:

就是统计x前面比它小的星星的个数,符合树状数组最基本的应用。

注意的是:树状数组下标为0的位置不可用,所以我们需要在输入x坐标时+1.

由于y坐标是升序的且坐标不重复,所以在星星A后面输入的星星的x,y坐标不可能都小于等于星星A。假如当前输入的星星为(3,3),易得我们只需要去找 树状数组中小于等于3的值就可以了,即GetSum(3)。注意:A[i]表示x坐标为i的个数,C[]A[]的树状数组,那么GetSum(i)就是 序列中前i个元素的和,即x小于等于i的星星数。

代码如下:

  1. #include<iostream>  
  2. #include<string>  
  3. #include<cstring>  
  4. #include<cstdio>  
  5. #include<algorithm>  
  6. using namespace std;  
  7.   
  8. #define CLR(arr, val) memset(arr, val, sizeof(arr))  
  9. #define N 32010  
  10.   
  11. int n;  
  12. int lev[N], c[N];  
  13.   
  14. int lowbit(int x)  
  15. {  
  16.     return x & (-x);  
  17. }  
  18.   
  19. void add(int i, int data)  
  20. {  
  21.     while(i < N)  
  22.     {  
  23.         c[i] += data;  
  24.         i += lowbit(i);  
  25.     }  
  26. }  
  27.   
  28. int getsum(int x)  
  29. {  
  30.     int res = 0;  
  31.     while(x > 0)  
  32.     {  
  33.         res += c[x];  
  34.         x -= lowbit(x);  
  35.     }  
  36.     return res;  
  37. }  
  38.   
  39. int main()  
  40. {  
  41.     int x, y;  
  42.     while(~scanf("%d", &n))  
  43.     {  
  44.         CLR(lev, 0); CLR(c, 0);  
  45.         for(int i = 0; i < n; ++i)  
  46.         {  
  47.             scanf("%d%d", &x, &y);  
  48.             x++; //有0出现,树状数组无法处理。故+1  
  49.             lev[getsum(x)]++; //先统计,不包括本身  
  50.             add(x, 1); //加入  
  51.         }  
  52.         for(int i = 0; i < n; ++i)  
  53.             printf("%d\n", lev[i]);  
  54.     }  
  55.     return 0;  
  56. }  

抱歉!评论已关闭.