树状数组(一)与poj2352 - stars

  

  昨天刚刚学习了树状数组的有关知识[1],完成了poj2352的编程与调试,下面是一些记录与感想。

  

  这题算是树状数组中较为简单的题目,中心思想是:

    由于y坐标为升序排列且坐标不重复,那么,在星星A后面的任意星星的横纵坐标不可能均小于星星A。那么,我们可以把(x,y)这样的坐标压缩在数组a[i]中,令a[i]记录横坐标为x的星星的个数。如果直接暴力求和的话,时间复杂度将为O(n2/2),会造成超时。我们使用树状数组进行求和,以压缩时间复杂度。

 

  我的代码如下:

 1 //在本题中,我们直接使用c数组进行累加,所以没有开a数组
 2 //<&x>为跳转符,与其后注释无关
 3 //以下是C++代码
 4 
 5 #include<cstdio>
 6 
 7 int n, c[40000] = {0}, ans[16000] = {0};   //n:星星的个数;c数组:用于构造树状数组;ans数组:用于累加;
 8 
 9 //这三个函数的证明在注释[1]中
10 inline int lowbit(const int &x);                      //lowbit:用于计算x^2
11 inline void doing_c(int x);                           //doing_c:用于更新树状数组
12 inline int getsum(int x);                             //getsum:用于求和
13 
14 int main()
15 {
16     scanf("%d", &n);
17     for(int i = 1; i <= n; ++i)
18     {
19         int x, y;
20         scanf("%d%d", &x, &y);
21         ++x;                                           //树状数组从c[1]开始处理,因为x=0时,<&x>处的while循环会出现死循环
22         ++ans[getsum(x)];
23         doing_c(x);
24     }
25     for(int i = 0; i < n ; ++i)
26     {
27         printf("%d\n", ans[i]);
28     }
29 }
30 
31 inline int lowbit(const int &x)
32 {
33     return x & (-x);
34 }
35 
36 inline void doing_c(int x)
37 {
38     while (x <= 32001)                                  //<&x>单组输入处理时,x的最大值未知,按照题目限制循环
39     {
40         ++c[x];
41         x += lowbit(x);
42     }
43 }
44 
45 inline int getsum(int x)
46 {
47     int s(0);
48     while(x > 0)                                         
49     {
50         s += c[x];
51         x -= lowbit(x);
52     }
53     return s;
54 }

 

  注意:1、第38行<&x>处的循环一定要循环到x的最大值,否则会造成后续统计的错误。(我懒得解释了……想一想为什么?)

  感想:这题虽说在各位dalao眼里十分简单,但是作为蒟蒻的我却做了一个下午(我是不会告诉你我被上面注释↑的内容卡了很久的)……默默感叹:啊,剧毒……我还是太弱了……

 

  注释:[1]:http://www.cnblogs.com/justforgl/archive/2012/07/27/2612364.html

 

 

  (转载请注明出处)

posted @ 2017-02-10 10:43  天宇之翼  阅读(150)  评论(0)    收藏  举报