樹狀數組

inline void add( LL s, LL num ){ while(s<=n) tree[s] += num,s += lowbit(s); return ; } inline LL ask (LL s) { LL ans = 0 ; while ( s >= 1) ans += tree [s] ,s -= lowbit(s); return ans; }

樹狀數組或者二叉索引樹也稱做Binary Indexed Tree,又叫作Fenwick樹;它的查詢和修改的時間複雜度都是log(n),空間複雜度則爲O(n),這是由於樹狀數組經過將線性結構轉化成樹狀結構,從而進行跳躍式掃描。一般使用在高效的計算數列的前綴和,區間和。html

其中a數組就是原數組,c數組則是樹狀數組,能夠發現c++

C1 = A1 C2 = A1+A2 C3 = A3 C4 = A1+A2+A3+A4 C5 = A5 C6 = A5+A6 C7 = A7 C8 = A1+A2+A3+A4+A5+A6+A7+A8

15=(1111)2,經過lowbit分解,它能夠變成4個數的和:(1111)2=(1)2+(10)2+(100)2+(1000)2,而後咱們分析這個倒着跳的過程。減去15的最小的2的冪次2^0獲得14。減去14的最小的2的冪次2^1獲得12。減去12的最小的2的冪次2^2獲得8。減去8的最小的2的冪次2^3獲得0。git

因此C(15) = C(14) + C(12) + C(8) + C(0),由圖也能夠得知,其結果是正確的。數組

除此以外,樹狀數組可以快速的求任意區間的和,設sum(k) = A[1] + A[2] + ... + A[k],則A[i] + A[i+1] + ... + A[j] = sum(j) - sum(i-1)。ide

#include <bits/stdc++.h>
#define rep(i,j,n) for(register int i=j;i<=n;i++)
#define Rep(i,j,n) for(register int i=j;i>=n;i--)
#define low(x) x&(-x)
using namespace std ;
typedef long long LL ;
const int inf = INT_MAX >> 1 ;
inline LL In() { LL res(0) , f(1) ; register char c ;
#define gc c = getchar()
    while(isspace(gc)) ; c == '-' ? f = - 1 , gc : 0 ;
    while(res = (res << 1) + (res << 3) + (c & 15) , isdigit(gc)) ;
    return res * f ;
#undef gc
}

inline void Ot() {
    while(1) {
        int x = In() ;
        cout << (low(x)) << '\n' ;
    }
}
signed main() {
//  freopen("test.in,"r",stdin) ;
    return Ot() , 0 ;
}
lowbit

lowbit是最低位 求法:x&(-x)spa

支持手工模擬code

 

#ifdef Dubug

#endif
#include <bits/stdc++.h>

#define lowbit(x) x&(-x)
using namespace std;
typedef long long LL ;
inline LL In() { LL res(0),f(1); register char c ;
    while(isspace(c=getchar())) ; c == '-'? f = -1 , c = getchar() : 0 ;
    while(res = (res << 1) + (res << 3) + (c & 15) , isdigit(c=getchar())) ;
    return res * f ;
}

LL n , q ;
const int N = 1e6 + 5 ;
LL tree[N] ;
inline void Add(int x,int y) {
    for(;x<=n;x+=lowbit(x)) tree[x] += y ;
}

inline LL ask(int x) {
    LL ans = 0 ;
    for(;x>=1;x-=lowbit(x)) ans += tree[x] ;
    return ans ;
}

signed main () {
    n = In() , q = In() ;
    for(register int i=1;i<=n;i++) {
        int x ;
        x = In() ;
        Add(i,x) ;
    }
    for(register int i=1;i<=q;i++) {
        int x , y , z ;
        x = In() , y = In() , z = In() ;
        if(x == 1) Add(y,z) ;
        if(x == 2) cout << ask(z) - ask(y-1) << endl ;
    }
    return 0 ;
}

 

超級樹狀數組 -> [Here]htm

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息