poj 2352 Stars

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的星星数。


代码如下:

[cpp]  view plain copy
  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. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值