树状数组——NYOJ士兵杀敌(二)

原帖 http://blog.sina.com.cn/s/blog_8e0ea6d50101snlj.html
写的有点小问题自行改了下
第一次做树状数组方面的题目,以前听学长讲过树状数组,但是当时候听的时候听他们讲到lowbit和什么进位运算的吧啦吧啦的时候我就闷了,觉得很复杂,这次遇见了树状数组的题目,没办法只能硬着头皮学了,结果发现对进位运算还是不了解,但是对lowbit的基本含义还是理解了的,赞一个。
先看看维基百科对树状数组的讲解吧。树状数组
预备函数
定义一个函数Lowbit(Int):Int,返回对参数转为二进制后,将最后一个1进位的结果.
例如,Lowbit(34)的返回值将是36.
将34转为二进制,为0010 0010,这里的"最后一个1"指的是从个位往前数,见到的第一个1,也就是"二位"上的1.
"进位"的操作,就是在这一位加1,也就是0010 0020,进位后,得0010 0100,也就是36.
程序上的实现,(Pascal中),((Not I)+1) And I表明了最后一位1的值,
仍然以34为例,Not 0010 0010的结果是 1101 1101(221),加一后为 1101 1110(222), 把 0010 0010与1101 1110作AND,得0000 0010(2).
显然,Lowbit的值,就是((Not I)+1) And I与I的和.
Lowbit的一个简便求法:(C/C++)int lowbit(int x){return x & (-x);}//注意此处lowbit没有所谓的进位容易误解汗~,我理解是lowbit就是二进制数从地位开始收个出现的‘1’的位置。
其实我们不必深究其中的运算,lowbit函数就是用来计算数组的下标的,可以看看百度百科上的对树状数组的图的描绘。

树状数组——NYOJ士兵杀敌(二)_第1张图片
树状数组——NYOJ士兵杀敌

lowbit就是用来构造下标的。例如当更新1的时候,2,4,8都得更新,更新3的时候4,8都得更新。。。lowbit就是将这些下标联系在一起的工具。
求和:列如我们要求1~4之间的和,我们只要求c4,c2,c1的和就行了。而这个就可以用lowbit来计算。
例题: NYOJ116士兵杀敌(二)
代码(很水,就不解释代码了)

#include
#define size 1000008

int C[size];
int len;
int lowbit(int i)
{
   return -i & i;
}
int sum(int i){
  int res=0;
  while(i>0){
    res+=C[i];
    i-=lowbit(i);
  }
  return res;

}
void add(int i,int x){
    while(i<=len){
        C[i]+=x;
        i+=lowbit(i);
    }
}
int main()
{
    int q;
    scanf("%d%d",&len,&q);
    int x;
    for(int i=1;i<=len;i++){
        scanf("%d",&x);
        add(i,x);
    }
    char operate[10];
    int star,end;
    while(q--){
            scanf("%s%d%d",operate,&star,&end);
            if(operate[0]=='A')
                add(star,end);
            else
               printf("%d\n",sum(end)-sum(star-1));
    }

}

你可能感兴趣的:(树状数组——NYOJ士兵杀敌(二))