Y1——树状数组入门
知识点
树状数组
树状数组多解决
计算数列的前缀和与区间和 的问题
时间复杂度:
O(logn)
相对于暴力枚举的O(n)级别快了不少
空间复杂度
O(n)
树状数组构成
树形结构表示数组,叶子结点存值
同时进行优化
优化:
用c[]表示子树的叶子结点的权值之和
使其中一些节点既表示a[i] 又表示和
如何知道哪些节点特殊??
1.将下标转为二进制
2.仔细观察
3.发现与二进制末尾0的个数有关
4.召唤神龙!!!(*@#*&#%^)
5.从下标i开始往前加2^k个数字,k就是0的个数
6.使用神奇的 lowbit(i) 运行完返回2^k
lowbit(i)
int lowbit(int t){
return t&(-t);
}
-t代表t的负数(计算机中使用对应的正数的补码表示)
单点修改
只修改与其相关的
咋找??
恭喜又问到了点上
i 每次增加 lowbit ( i )
代码
void update(int x,int y){//x为更新的位置,y为a[x]的变化量,n为数组最大值 for(int i=x;i<=n;i+=lowbit(i)){c[i]+=y;}
}
区间查询
代码
注意当数据较大时,int函数变一下long long
int getsum(int x){int ans=0;for(int i=x;i;i-=lowbit(i)){ans+=c[i];}return ans;
}
题
BIT-1
题目描述
给定数组�1,�2...��a1,a2...an,进行q次操作,操作有两种:
1 i x
:将��ai加上 x;
2 l r
:求��+...+��al+...+ar
输入描述
第一行:输入两个数 n,q,表示给定数组的长度和操作数
第二行:输入n个数,表示长度为n的给定数组
接下来q行:每行输入3个数字,表示如题的某一种操作
输出描述
对于每个2操作,输出对应结果
输入样例
3 2
1 2 3
1 2 1
2 1 3
输出样例
7
数据描述
1≤�,�≤1061≤n,q≤106
∣��∣≤106∣ai∣≤106
对于输入:保证1≤�≤�≤�,∣�∣≤1061≤l≤r≤n,∣x∣≤106
代码
#include<bits/stdc++.h>
using namespace std;
long long c[1000005];
int n,q,a[1000005],x,y,r;
int lowbit(int t){return t&(-t);
}
void update(int x,int y){//x为更新的位置,y为a[x]的变化量,n为数组最大值 for(int i=x;i<=n;i+=lowbit(i)){c[i]+=y;}
}
//long long
long long getsum(int x){long long ans=0;for(int i=x;i;i-=lowbit(i)){ans+=c[i];}return ans;
}
int main(){scanf("%d%d",&n,&q);for(int i=1;i<=n;i++){scanf("%d",&a[i]);update(i,a[i]);} for(int i=1;i<=q;i++){scanf("%d%d%d",&r,&x,&y);if(r==1){update(x,y);}else{printf("%lld\n",getsum(y)-getsum(x-1));}}return 0;
}