树状数组(一)与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
(转载请注明出处)

浙公网安备 33010602011771号