[转]树状数组的一些应用

树状数组(BIT,Binary Indexed Tree)

先上一张经典的图吧。(也是盗的,地址见水印

以下转自:http://blog.csdn.net/lawrence_jang/article/details/8054173

1.单点增减+区间求和

思路:C[x]表示该点的元素:sum(x)=C[1]+C[2]+……C[x]

int arr[MAXN];
inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}
inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}
inline int query(int x,int y){return sum(y)-sum(x-1);} 

2.区间增减+单点查询

思路:C[x]表示该点元素与左边元素的差值:num[x]=C[1]+C[2]+……C[x]

int arr[MAXN]
inline int sum(int x){int res=0;while(x)res+=arr[x],x-=lowbit(x);return res;}
inline void add(int x,int n){while(x<MAXN)arr[x]+=n,x+=lowbit(x);}
inline int update(int x,int y,int n){add(x,n);add(y+1,-n);}  

3.区间增减+区间查询

思路:C[x]表示该点元素与左边的差值

sum(sum(C[j],j<=i)i<=x)  =  x*C[1]+(x-1)*C[2]+……+C[x]  =  (x+1)*sum(C[i],i<=x)-sum(i*C[i],i<=x);

则可以想到用C1[x]维护C[x]的值,C2[x]维护x*C[X]的值

struct tree_array{
    struct tree_array_single{
        int arr[MAXN];
        void add(int x, int v) { while(x <= N) arr[x] += v, x += lowbit(x); }
        int sum(int x) { int sum = 0; while(x) sum+=arr[x], x-=lowbit(x); return sum; }
    } T1, T2;
    void reset() { memset(T1.arr, 0, sizeof T1.arr); memset(T2.arr, 0, sizeof T2.arr); }
    void add(int x, int v) { T1.add(x, v); T2.add(x, x*v); }
    void update(int L, int R, int v) { add(L, v); add(R+1, -v); }   // [L,R]每个点值都增加v
    int sum(int x) { return (x+1)*T1.sum(x)-T2.sum(x); }            // 前x个数的和
    int query(int L,int R) { return sum(R)-sum(L-1); }              // 区间[L,R]的和
};

4.二维:单点增减(add) + 矩形求和(query)+ 矩形增减(update)+ 单点求值(sum)

int arr[MAXN][MAXN]
inline void add(int x,int y,int v) {
    for(int i=x;i<MAXN;i+=lowbit(i))
        for(int j=y;j<MAXN;j+=lowbit(j))
            arr[i][j]+=v;
}
inline int sum(int x,int y){
    int res=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            res+=arr[i][j];
    return res;
}
inline int query(int L,int B,int R,int T) {
    return sum(R,T)+sum(L-1,B-1)-sum(R,B-1)-sum(L-1,T);
}
inline void update(int L,int B,int R,int T,int v){  // 左 下 右 上 要增加的值
    add(L,B,v); add(L,T+1,v); add(R+1,B,v); add(R+1,T+1,v);
} 

5.单点增减(add) + 立方体求和(query)+ 立方体增减(update) + 单点求值(sum)

int arr[MAXN][MAXN][MAXN];
inline int sum(int x,int y,int z){
    int res=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            for(int k=z;k;k-=lowbit(k))
                res^=arr[i][j][k];
    return res;
}
inline void add(int x,int y,int z,int v){
    for(int i=x;i<MAXN;i+=lowbit(i))
        for(int j=y;j<MAXN;j+=lowbit(j))
            for(int k=z;k<MAXN;k+=lowbit(k))
                arr[i][j][k]+=v;
}
inline void update(int x1,int y1,int z1,int x2,int y2,int z2,int v){
    add(x1,y1,z1,v);
    add(x2+1,y1,z1,-v);add(x1,y2+1,z1,-v);add(x1,y1,z2+1,-v);
    add(x2+1,y2+1,z1,v);add(x2+1,y1,z2+1,v);add(x1,y2+1,z2+1,v);
    add(x2+1,y2+1,z2+1,-v);
}
inline int query(int x1,int y1,int z1,int x2,int y2,int z2){
    return sum(x2,y2,z2)
    -sum(x2,y2,z1-1)-sum(x2,y1-1,z2)-sum(x1-1,y2,z2)
    +sum(x2,y1-1,z1-1)+sum(x1-1,y2,z1-1)+sum(x1-1,y1-1,z2)
    -sum(x1-1,y1-1,z1-1);
}

6.RMQ

inline void init()
{
    memset(arr, 0, sizeof arr);
    for(int i=1;i<=N;++i)
        for(int j=i;j<=N&&arr[j]<num[i];j+=lowbit(j))
            arr[j]=num[i];
}
inline int query(int L,int R)
{
    int res=0;
    for(--L;L<R;){
        if(R-lowbit(R)>=L){res=max(res,arr[R]);R-=lowbit(R);}
        else{res=max(res,num[R]);--R;}
    }
    return res;
}
inline void update(int x,int val)
{
    int ori=num[x];
    num[x]=val;
    if(val>=ori)
        for(int i=x;i<=N&&arr[i]<val;i+=lowbit(i))
            arr[i]=val;
    else{
        for(int i=x;i<=N&&arr[i]==ori;i+=lowbit(i))
        {
            arr[i]=val;
            for(int j=lowbit(i)>>1;j;j>>=1)
                arr[i]=max(arr[i],arr[i-j]);
        }
    }
}
时间: 2024-10-11 10:51:55

[转]树状数组的一些应用的相关文章

树状数组(Binary Indexed Tree,BIT)

树状数组(Binary Indexed Tree) 前面几篇文章我们分享的都是关于区间求和问题的几种解决方案,同时也介绍了线段树这样的数据结构,我们从中可以体会到合理解决方案带来的便利,对于大部分区间问题,线段树都有其绝对的优势,今天这篇文章,我们就来欣赏由线段树变形的另外一个数据结构--树状数组,树状数组通常也用于解决区间求和.单点更新的问题,而且效率比线段树高一些(树状数组区间求和和单点更新的时间复杂度均为o(log n)),相对而言,线段树的应用范围可能更广泛一些.但不得不承认,树状数组确

ACM数据结构-树状数组

模板: int n; int tree[LEN]; int lowbit(int x){ return x&-x; } void update(int i,int d){//index,delta while(i<=n){ tree[i]+=d; i+=lowbit(i); } } int getsum(int i){ int ans=0; while(i>0){ ans+=tree[i]; i-=lowbit(i); } return ans; } 示意图: 1.Ultra-Quic

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

(POJ 3067) Japan (慢慢熟悉的树状数组)

Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 29295   Accepted: 7902 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coas

【二维树状数组】See you~

https://www.bnuoj.com/v3/contest_show.php?cid=9148#problem/F [题意] 给定一个矩阵,每个格子的初始值为1.现在可以对矩阵有四种操作: A x y n1 :给格点(x,y)的值加n1 D x y n1: 给格点(x,y)的值减n1,如果现在格点的值不够n1,把格点置0 M x1 y1 x2 y2:(x1,y1)移动给(x2,y2)n1个 S x1 y1 x2 y2 查询子矩阵的和 [思路] 当然是二维树状数组 但是一定要注意:lowbi

Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒[email protected][email protected]). 但是,战壕有一个弱点,就是只能攻击它的左下方,说白了就是横纵坐标都不大于它的点(mx:“我的战壕为什么这么菜”ToT).这样,永恒就可以从别的地方进攻摧毁战壕,从而消灭mx的部队. 战壕都有一个保护范围,同它的攻击

CF 313 DIV2 B 树状数组

http://codeforces.com/contest/313/problem/B 题目大意 给一个区间,问你这个区间里面有几个连续相同的字符. 思路: 表示个人用树状数组来写的...了解了树状数组的本质就行了. 当然用sum[r]-sum[l]也是可以的

Hdu5032 极角排序+树状数组

题目链接 思路:参考了题解.对询问进行极角排序,然后用树状数组维护一下前缀和即可. /* ID: onlyazh1 LANG: C++ TASK: test */ #include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 typedef long long ll; const int maxn=1010; const int maxm=10

Curious Robin Hood(树状数组+线段树)

1112 - Curious Robin Hood    PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB Robin Hood likes to loot rich people since he helps the poor people with this money. Instead of keeping all the money together he does another tri