树状数组
树状数组是一个完全二叉树的变形
树状数组用O(logn)时间来求一个数组中任意前缀和,并且能修改 O(logn)。
空间复杂度为O(n)
可以推出这样一个规律:X的末尾有几个0,则相加2^(0的个数 )个数
cx=a[x]+a[x-1]
总结公式
c
[
i
]
=
a
[
i
−
2
k
+
1
]
+
a
[
i
−
2
k
+
2
]
+
.
.
.
.
.
.
.
+
a
[
i
]
c[i]=a[i-2^k+1]+a[i-2^k+2]+.......+a[i]
c[i]=a[i−2k+1]+a[i−2k+2]+.......+a[i]
lowbit
lowbit(x)是用来求x的最低位1,lowbit(x)=2^k。
lowbit(int t){return t&(-t);}
修改
修改用于过程中
或输入时
使用。
c[3]=a[3]; c[4],c[8]要改。
void xiugai(int x,int y){//求 将原数组的a[x]修改为y 的前缀和数组
for(int i=x;i<=n;i+=lowbit(i)){
c[i]+=y;
}
3(0011)+lowbit(3) ->4(0100)+lowbit(4) ->8(1000)
区间查询
sum[7]=c[4]+c[6]+c[7];
二进制:sum[(111)]=c[(100)]+c[(110)]+c[(111)]。
7(111) -lowbit(7) -> 6(110)-lowbit(8) -> 4(100) -lowbit(4) ->0
int chaxun(int x){//求1~x的前缀和
long long sum=0;
for(int i=x;i>0;i-=lowbit(i)){
sum+=c[i];
}
return sum;
通过树状数组求最长上升子序列
求最长上升子序列的动态转移方程
:dp[i]=max{dp[j]+1 | j<i&&a[j]<a[i];
代码:
差分
通过O(1)
时间复杂度,实现一段区间的修改
(1)求差分数组
(2)将差分数组c[l]加上要加的数,c[r+1]减去加上的数
(3)输出前求一遍差分数组的前缀和,输出前缀和数组
· ·前缀和··
前缀和与差分互为逆运算
BIT-2
隐式类型转换
兼容度较低的类型加兼容度较高的类型得数为兼容度较高的类型