树状数组贼强。
树状数组支持单点修改和区间求和。
树状数组的精髓在于lowbit数组,lowbit[i]是将i化为二进制后从右往左第一位数字为1的位置代表的值。
比如: 8化成二进制是100,从右往左数第三位是第一个1,代表的值是8.
如何求lowbit呢?
这里有一个很神奇的操作:
int lowbit(int t)//求lowbit
{
return t&(-t);
}
我也不会证明。
单点修改:
void change(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))
tree[i]+=y;
}
x是要修改那个点的序号,y是修改值。
通过类似于递归的形式把与第x个点有关的值都修改。
求和
long long add(int x)
{
long long ans=0;
for(int i=x;i>0;i-=lowbit(i))
ans+=tree[i];
return ans;
}
运用了二进制的规律。
一道简单的例题:
只要把上面几个函数结合运用就行了。
include<bits/stdc++.h>
using namespace std;
int tree[100011]={0};
int a[100011]={0};
int ans1=0,ans=0;
int n,m;
int x,y;
int lowbit(int t)
{
return t&(-t);
}
void change(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))
tree[i]+=y;
}
long long add(int x)
{
long long ans=0;
for(int i=x;i>0;i-=lowbit(i))
ans+=tree[i];
return ans;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
change(i,a[i]);
}
char c;
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>c;
if(c=='Q')
{
cin>>x>>y;
cout<<add(y)-add(x-1)<<endl;
}
else
{
cin>>x>>y;
change(x,y-a[x]);
a[x]=y;
}
}
return 0;
}
欢乐水博客!