树状数组模板

【模板】树状数组 1  点我

代码:

#include <iostream>
using namespace std;
int c[500001],n,m,t1,t2,t3;
int lowbit(int x)
{
    return x&-x;
}
void update(int x,int k)
{
    for(int i=x;i<=n;i+=lowbit(i))
        c[i]+=k;
}
int sum(int x)
{
    int ans=0;
    for(int i=x;i>0;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;i++)
    {
        cin >> t1;
        update(i,t1);
    }
    for(int i=1;i<=m;i++)
    {
        cin >> t1 >> t2 >> t3;
        if(t1==1)
            update(t2,t3);
        if(t1==2)
            cout << sum(t3)-sum(t2-1) << endl;
    }
    return 0;
}

 【模板】树状数组 2  点我

代码:

#include <iostream>
using namespace std;
int c[500001],n,m,t1,t2,t3,t4;
int lowbit(int x)
{
    return x&-x;
}
void update(int l,int r,int k)
{
    for(int i=l;i<=n;i+=lowbit(i))
        c[i]+=k;
    for(int i=r+1;i<=n;i+=lowbit(i))
        c[i]-=k;
}
int sum(int x)
{
    int ans=0;
    for(int i=x;i>0;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
int main()
{
    cin >> n >> m;
    for(int i=1;i<=n;i++)
    {
        cin >> t1;
        update(i,i,t1);
    }
    for(int i=1;i<=m;i++)
    {
        cin >> t1 >> t2;
        if(t1==1)
        {
            cin >> t3 >> t4;
            update(t2,t3,t4);
        }
        if(t1==2)
            cout << sum(t2) << endl;
    }
    return 0;
}

 关于lowbit:

大家看看这张图,我列举出了各个元素的lowbit值。我们可以发现,lowbit(x)=father(x)-x。father[x]代表x的父亲(比如图中1的父亲是2,3的父亲是4,6的父亲是8)。

另外我们还可以发现,lowbit(x)=x-lastbrother(x)。lastbrother(x)代表x的前一个兄弟。如果x是第一个兄弟,则lastbrother(x)=0。

比如图中4的前一个兄弟是0,6的前一个兄弟是4,7的前一个兄弟是6。

树状数组在没有区间max的情况下可以代替线段树,比线段树快的不知道 哪里去了

具体看代码

#include<bits/stdc++.h>
using namespace std;
#define maxn 100000
#define lowbit(x) ((x)&(-(x))) 
int n,m,t,x,y;
long long w;
struct tagTreeArray
{
    long long c[maxn],a[maxn];//前者存i*a[i],后者存差分
    void upd(int x,long long k)//x...inf区间加一个数 
    {
        for(int i=x;i<=n;i+=lowbit(i))
        {
            c[i]+=x*k;
            a[i]+=k;
        }
    }
    long long query(int x)//查询1...x区间和 
    {
        long long ans1=0,ans2=0;
        for(int i=x;i>0;i-=lowbit(i))
        {
            ans1+=a[i];
            ans2+=c[i];
        }
        return ans1*(x+1)-ans2;
    }
    void add(int l,int r,long long k)//[l,r]加一个数 
    {
        upd(l,k);
        upd(r+1,-k);
    }
    long long query(int l,int r)//查询l...r区间和 
    {
        return query(r)-query(l-1);
    }
}arr;

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&x);
        arr.add(i,i,x);
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&t);
        if(t==1)
        {
            scanf("%d%d%lld",&x,&y,&w);
            arr.add(x,y,w); 
        }
        if(t==2)
        {
            scanf("%d%d",&x,&y);
            printf("%lld\n",arr.query(x,y));
        }
    }
}

 

posted @ 2018-09-06 09:19  ghj1222  阅读(181)  评论(0编辑  收藏  举报