树状数组(2)

来源:互联网 发布:网络新词贫民窟女孩 编辑:程序博客网 时间:2024/06/05 18:26

操作:区间修改,求单点值。
转化思路:把对区间的修改转化为修改两次点的值。

设输入数据储存在a[i]中。
设b[i]=a[i]-a[i-1]。

则任意点x的值可以表示为
这里写图片描述

修改区间的指令add(l,r,x)即可转化为:
b[l]+=x; b[r+1]-=x;

对于S数组,又是求和的表示形式,可以交给BIT。
假设用c[]来充当S[]的BIT,则
c[x]=S[x]-S[x-lowbit(x)]
=这里写图片描述
=a[i]-a[x-lowbit(x)]
所以在具体实现中,只需要两个数组a[]和c[]即可完成操作。

查询query(x)用BIT的基本查询操作完成。

#include <cstdio>#include <iostream>using namespace std;#define maxn 100000+10long n,m,l,t,x;long a[maxn],c[maxn];long lowbit(long x){    return x&(-x);}void read(){    cin>>n;    for(long i=1;i<=n;i++)        cin>>a[i];    for(long i=1;i<=n;i++)        c[i]=a[i]-a[i-lowbit(i)];}void add(long k,long x){    for(;k<=n;k+=lowbit(k))        c[k]+=x;}void query(long k){    long sum=0;    for(;k>0;k-=lowbit(k))        sum+=c[k];    cout<<sum<<endl;}void work(){    cin>>m;    for(long i=1;i<=m;i++)    {        int p;        cin>>p;        if(p==1)        {            cin>>l>>t>>x;            add(l,x);            add(t+1,-x);        }        else        {            cin>>x;            query(x);        }    }}int main(){    ios::sync_with_stdio(false);    read();    work();    return 0;}
0 0
原创粉丝点击