数状数组刚刚学习起来其实还是有点懵逼的
但是其本质其实就是用二进制对数组下标进行操作,从而建树
每个节点k的父节点是 k + lowbit(k)
这边的lowbit有点难理解,自己手动算几次 k&-k就可以理解了
其实得到的是二进制 k的最低位的1
比如 lowbit(5)=1 5的二进制是101
lowbit(6)=2 6的二进制是110 最低位在是第二位 (10)b=(2)十进制
在k±=lowbit(k)的过程就是不断对二进制位近位或者降位
数状数组只能支持两个操作:
(1): 单点增加值
(2):前缀查询 查询区间 [ 1, x ]的前缀和
其他操作都不是很支持 连单点查询都不方便 。。。。
建树的操作就是基于单点增加值来说的
初始化一个全为0的数组 然后进行单点更新
数状数组求逆序对个数
模板
#include<iostream>
#include<stdio.h>
#include<string.h>
#define max 100
int tree[max];
int n;
int lowbit(int k){
return k&-k;
}
void update(int index,int num){ //单点更新
while(index<=n){
tree[index]+=num;
index+=lowbit(index);
}
}
int request(int r){//查询【1,r】的总和
int sum=0;
while(r){
sum+=tree[r];
r-=lowbit(r);
}
return sum;
}
int main(){
scanf("%d",&n);
int temp;
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++){
scanf("%d",&temp);
update(i,temp);
}
for(int i=1;i<=n;i++){
printf("%d\n",request(i));
}
return 0;
}