<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      BIT 樹狀數組 詳解 及 例題

      (一)樹狀數組的概念  

      如果給定一個數組,要你求里面所有數的和,一般都會想到累加。但是當那個數組很大的時候,累加就顯得太耗時了,時間復雜度為O(n),并且采用累加的方法還有一個局限,那就是,當修改掉數組中的元素后,仍然要你求數組中某段元素的和,就顯得麻煩了。所以我們就要用到樹狀數組,他的時間復雜度為O(lgn),相比之下就快得多。下面就講一下什么是樹狀數組:

          一般講到樹狀數組都會少不了下面這個圖:

      下面來分析一下上面那個圖看能得出什么規律:

               據圖可知: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,c9=a9,c10=a9+a10,c11=a11........c16=a1+a2+a3+a4+a5+.......+a16。

               分析上面的幾組式子可知,當 i 為奇數時,ci=ai ;當 i 為偶數時,就要看 i 的因子中最多有二的多少次冪,例如,6 的因子中有 2 的一次冪,等于 2 ,所以 c6=a5+a6(由六向前數兩個數的和),4 的因子中有 2 的兩次冪,等于 4 ,所以 c4=a1+a2+a3+a4(由四向前數四個數的和)。

              (一)有公式:cn=a(n-a^k+1)+.........+an(其中 k 為 n 的二進制表示中從右往左數的 0 的個數)。

               那么,如何求 a^k 呢?求法如下:

      1 int lowbit(int x) //取x的最低位1,比如4,則返回4,如5,則返回1
      2 {
      3     return x&(-x);
      4 }
      View Code

      lowbit()的返回值就是 2^k 次方的值。

               求出來 2^k 之后,數組 c 的值就都出來了,接下來我們要求數組中所有元素的和。

               (二)求數組的和的算法如下:

               (1)首先,令sum=0,轉向第二步;

               (2)接下來判斷,如果 n>0 的話,就令sum=sum+cn轉向第三步,否則的話,終止算法,返回 sum 的值;

               (3)n=n - lowbit(n)(將n的二進制表示的最后一個零刪掉),回第二步。

                代碼實現:

       1 int Sum(int i)   //求前i項的和
       2 {
       3     int s = 0;
       4     //將前i項分段
       5     while(i > 0)
       6     {
       7         s += sum[i];
       8         i -= lowbit(i);  //去掉i的二進制最后一個
       9     }
      10     return s;
      11 }
      View Code

       (三)當數組中的元素有變更時,樹狀數組就發揮它的優勢了,算法如下(修改為給某個節點 i 加上 x ):

               (1)當 i<=n 時,執行下一步;否則的話,算法結束;

               (2)ci=ci+x ,i=i+lowbit(i)(在 i 的二進制表示的最后加零),返回第一步。

                代碼實現:

      1 void update(int i, int val)  //將第i個元素增加val
      2 {
      3     //i的祖先都要增加val
      4     while(i <= n)
      5     {
      6         sum[i] += val;
      7         i += lowbit(i);   //將i的二進制未位補為得到其祖先
      8     }
      9 }
      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}.此時具體的操作如應用一

      以下數組下標均默認從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:改變更新路徑和求和路徑

       

       1 void update(int x, int val)
       2 {
       3     for(int i=x; i>0; i-=lowbit(i))
       4     {
       5         sum[i] += val;
       6     }
       7 }
       8 
       9 int getSum(int x)
      10 {
      11     int s = 0;
      12     for(int i=x; i<MAXN; i+=lowbit(i))
      13     {
      14         s += sum[i];
      15     }
      16     return s;
      17 }
      View Code

       

      應用三  逆序數

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

      操作:應用一位置i的左邊,應用三是位置i的右邊。 然后只需要在應用一的基礎上從后往前操作即可

       

      1 for(int i=n; i>=1; i--)
      2 
      3 {
      4 
      5 b[i] = getSum(a[i]); //求前a[i]項的和
      6 
      7 update(a[i],1);      //第a[i]個元素+1
      8 
      9 }
      View Code

       

      應用四

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

      操作:只需將數組a倒過來編號,即將a轉化為 a[]={4,1,3,2,5} 然后利用應用三

       

       

      二維樹狀數組

       1 int lowbit(int x)
       2 {
       3     return x&(-x);
       4 }
       5 
       6 void update(int x, int y, int val) //將 a[x][y] 的值增加val
       7 {
       8     for(int i=x; i<N; i+=lowbit(i))
       9     {
      10         for(int j=y; j<N; j+=lowbit(j))
      11         {
      12             sum[i][j] += val;
      13         }
      14     }
      15 }
      16 
      17 
      18 int getSum(int x, int y) //求以1,1為左上角端點,學校,x,y為右下角端點的矩陣和.
      19 {
      20     int s = 0;
      21     for(int i=x; i>0; i-=lowbit(i))
      22     {
      23         for(int j=y; j>0; j-=lowbit(j))
      24         {
      25             s += sum[i][j];
      26         }
      27     }
      28     return s;
      29 }
      View Code

      (三)例題

      基礎應用

      HDU 1166 敵兵布陣(樹狀數組)

      http://www.rzrgm.cn/ws5167/p/3904004.html

      HDU 2689 Sort it (樹狀數組)

      http://www.rzrgm.cn/ws5167/p/3915614.html

       

      HDU 2492 Ping pong (樹狀數組)

       

      HDU Cow Sorting (樹狀數組)

       

       

       

      二維樹狀數組

       

      HDU1559 最大子矩陣 (二維樹狀數組)

      HDU 1892 See you~ (二維樹狀數組)

       

       

      三維樹狀數組

       

      HDU 3584 Cube (三維 樹狀數組)

       

      樹狀數組求逆序數

      HDU 1394 Minimum Inversion Number ( 樹狀數組求逆序數 )

       

      DP+樹狀數組+離散化

      HDU 2227 Find the nondecreasing subsequences (DP+樹狀數組+離散化)

       

       
       

       

      posted @ 2014-08-15 20:22  四十四次日落  Views(483)  Comments(1)    收藏  舉報
      主站蜘蛛池模板: 精品国产一区二区三区四区阿崩| 国产一区二区日韩在线| 欧美人与动牲交A免费观看| 亚洲伊人精品久视频国产| 综合偷自拍亚洲乱中文字幕| 一区一区三区产品乱码| 欧美巨大巨粗黑人性aaaaaa| 99久久精品国产一区二区暴力| 日韩一区二区三区女优丝袜| 亚洲av第三区国产精品| 欧美日韩高清在线观看| 亚洲 日本 欧洲 欧美 视频| 国产精品三级黄色小视频| 精品国产成人午夜福利| 色欲精品国产一区二区三区av| 熟女精品色一区二区三区| 精品国产美女福到在线不卡| 长岭县| 亚洲av伦理一区二区| 国产一区二区精品偷系列| 久久五十路丰满熟女中出| 国产精品国产三级国快看| 欧美成人h精品网站| 亚洲熟妇av综合一区二区| 国内精品久久人妻无码妲| 亚洲国产精品高清线久久| 亚洲精品韩国一区二区| 少妇爆乳无码专区| japanese无码中文字幕| 九九热在线免费观看视频| 久久精品亚洲中文无东京热| 国产精品熟女亚洲av麻豆| 国产一区二区三区尤物视频| 人妻色综合网站| 国产午夜在线观看视频播放| 久久精品人妻少妇一区二| 天干天干天啪啪夜爽爽99| 精品久久综合日本久久网| 久久这里有精品国产电影网| av午夜福利一片免费看久久| 国产jizzjizz视频|