Binary Indexted Tree 樹狀數組入門

來源:互聯網
上載者:User

標籤:通過   tar   view   ref   play   樹狀數組   下標   資料結構   .com   

感謝http://www.cnblogs.com/xudong-bupt/p/3484080.html

樹狀數組(BIT)是能夠完成下述操作的資料結構:

  給定一初始值全為零的數列a1,a2a,a3...,an

  1.給定i,計算a1+a2+...+ai

  2.給定i和x,執行ai+=x

 

BIT的結構:

數組bit[N]

  bit[1]=C1=A1;bit[2]=C2=C1+A2;

  BIT就是使用數組來維護上面所說的部分和

  以1結尾的1,3,5,7長度為1

  以1個0結尾的2,6長度為2

  以兩個0結尾的4長度為4

這樣,編號的二進位就能和區間對應起來

通過這個性質,實現上述功能

 

修改操作 :

修改a[k]後,c數組的哪些元素受到影響? 

p1=k肯定受到影響, 設pi的父親為p(i+1),則

p(i+1)=pi+2^L,L為pi二進位中末尾0的個數

給a[3]增加x,則p1=3, p2=3+20=4, p3=4+22=8, p4=8+23=16>9,因此修改c[3],c[4],c[8]

它所有的後繼(祖先)受影響

找後繼

求和操作 :

設要求前k項的和,則從最後一項開始 k1=k

 k(i+1)=ki-2^s,

s為ki二進位末尾0的個數  k=7,

則k1=7, k2=k1-20=6, k3=k2-21=4, k4=k3- 22=0,

因此前7項和為c[7]+c[6]+c[4]

 

  1) a[]: 儲存未經處理資料的數組。(操作(1)求其中連續多個數的和,操作(2)任意修改其中一個元素)

    e[]: 樹狀數組,其中的任意一個元素e[i]可能是一個或者多個a數組中元素的和。如e[2]=a[1]+a[2]; e[3]=a[3]; e[4]=a[1]+a[2]+a[3]+a[4]。 

  2) e[i]是幾個a數組中的元素的和?

    如果數字 i 的二進位表示中末尾有k個連續的0,則e[i]是a數組中2^k個元素的和,則e[i]=a[i-2^k+1]+a[i-2^k+2]+...+a[i-1]+a[i]。

    如:4=100(2)  e[4]=a[1]+a[2]+a[3]+a[4];

      6=110(2)  e[6]=a[5]+a[6]

      7=111(2)  e[7]=a[7]

  3) 後繼:可以理解為節點的父親節點。是離它最近的,且編號末位連續0比它多的就是它的父親,如e[2]是e[1]的後繼;e[4]是e[2]的後繼。

      如e[4] = e[2]+e[3]+a[4] = a[1]+a[2]+a[3]+a[4] ,e[2]、e[3]的後繼就是e[4]。

      後繼主要是用來計算e數組,將當前已經計算出的e[i]添加到他們後繼中。

    前驅:節點前驅的編號即為比自己小的,最近的,最末連續0比自己多的節點。如e[7]的前驅是e[6],e[6]的前驅是e[4]。

        前驅主要是在計算連續和時,避免重複添加元素。

      如:Sum(7)=a[1]+...+a[7]=e[7]+e[6]+e[4]。(e[7]的前驅是e[6], e[6]的前驅是e[4])

    計算前驅與後繼:

      lowbit(i) = ( (i-1) ^ i) & i ;

      節點e[i]的前驅為 e[ i - lowbit(i) ];

      節點e[i]的後繼為 e[ i + lowbit(i) ]

核心思想:

    (1)樹狀數組中的每個元素是原數組中一個或者多個連續元素的和。

    (2)在進行連續求和操作a[1]+...+a[n]時,只需要將樹狀數組中某幾個元素的和即可。時間複雜度為O(lgn)

    (3)在進行修改某個元素a[i]時,只需要修改樹狀數組中某幾個元素的和即可。時間複雜度為O(lgn)

 

一維樹狀數組常用的3個函數

int lowbit(int x) //取x的最低位1,比如4,則返回4,如5,則返回1{    return x&(-x);}void update(int i, int val)  //將第i個元素增加val{    //i的祖先都要增加val    while(i <= n)    {        sum[i] += val;        i += lowbit(i);   //將i的二進位未位補位得到其祖先    }}int Sum(int i)   //求前i項的和{    int s = 0;    //將前i項分段    while(i > 0)    {        s += sum[i];        i -= lowbit(i);  //去掉i的二進位最後一個    }    return s;}

準系統

#include<iostream>#include<cstring>#include<cstdio>using namespace std;char order[10];int a[50010];inline int lowbit(int k){    return k&-k;}inline void update(int i,int N,int plus)///界限N,為第i項加上plus,對應包含它的項也要改變{    while(i<=N)    {        a[i]+=plus;        i+=lowbit(i);///後繼改變    }}inline int getsum(int k)///求第1到第k項的和{    int sum=0;    while(k)    {        sum+=a[k];        k-=lowbit(k);    }    return sum;}int main(){    int n;    while(~scanf("%d",&n))    {        memset(a,0,sizeof(a));        int x;        for(int i=1;i<=n;i++)        {            scanf("%d",&x);            update(i,n,x);        }        for(int i=1;i<=n;i++)        {            printf("%d ",a[i]);        }        printf("求前5項和:\n");        printf("%d\n",getsum(5));        printf("求3-6項和:\n");        printf("%d\n",getsum(6)-getsum(3)+a[3]);    }    return 0;}
View Code

 

 

以下數組下標均預設從1開始

應用一

假如給你一個數組a[ ] = {2,5,3,4,1},求b[i],b[i] 表示在a[1],a[2]...a[i-1]中(即位置i的左邊)小於等於a[i]的數的個數。對此例b[] = {0,1,1,2,0}。 那麼該如何去求得b[i]呢?

解法:假如要得到b[4]的值,對於a[4] = 4. 我們 只要得到在a[1],a[2],a[3] 中出現小於等於4的個數,即1,2,3,4的個數,此例即為2. a[1] = 2 < a[4], a[3] = 3 < a[4]. 所以b[4] = 2;其他的以此類推. 求b[i]的值,需要得到在a[1],a[2]....a[i-1]中出現小於等於a[i]的個數,即1,2...a[i]的個數. 相當於求前a[i]項的和,可用到樹狀數組. 

具體操作

for(int i=1; i<=n; i++)

{

b[i] = getSum(a[i]); //求前a[i]項的和

update(a[i],1);      //第a[i]個元素+1

}

應用二

假如給你一個數組a[ ] = {2,5,3,4,1},求b[i],b[i] 表示在a[1],a[2]...a[i-1]中(即位置i的左邊)大於等於a[i]的數的個數。對此例b[] = {0,0,1,1,4}。 那麼該如何去求得b[i]呢?

解法1: 只需要先將數組a倒過來編號,即將a轉換為,a[] ={4,1,3,2,5}.此時具體的操作如應用一

解法2:改變更新路徑和求和路徑

 

Binary Indexted Tree 樹狀數組入門

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.