zoukankan      html  css  js  c++  java
  • 树状数组

    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),这是因为树状数组通过将线性结构转化成树状结构,从而进行跳跃式扫描。通常使用在高效的计算数列的前缀和,区间和。

    其中a数组就是原数组,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。

    所以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)。

    #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)) << '
    ' ;
        }
    }
    signed main() {
    //  freopen("test.in,"r",stdin) ;
        return Ot() , 0 ;
    }
    lowbit

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

    支持手工模拟

    #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]

    不存在十全十美的文章 如同不存在彻头彻尾的绝望
  • 相关阅读:
    SQL Server 2012 自动增长列,值跳跃问题(自增增加1000)
    根据城市表生成json数据
    LeetCode_257. Binary Tree Paths
    LeetCode_242. Valid Anagram
    LeetCode_237. Delete Node in a Linked List
    LeetCode_235. Lowest Common Ancestor of a Binary Search Tree
    LeetCode_234. Palindrome Linked List
    LeetCode_232. Implement Queue using Stacks
    LeetCode_231. Power of Two
    LeetCode_225. Implement Stack using Queues
  • 原文地址:https://www.cnblogs.com/qf-breeze/p/10526636.html
Copyright © 2011-2022 走看看