主要看圖
i往上找就是i+=2^k; 往下就是減 k是i的二進位制右邊0的個數
2^k 直接等於i&(-i);
傳送門:寫的很好
總結 首先,明白樹狀陣列所白了是按照二分對陣列進行分組;維護和查詢都是o(lgn)的複雜度,複雜度取決於最壞的情況,也是o(lgn);lowbit這裡只是乙個技巧,關鍵在於明白c陣列的構成規律;分析的過程二進位制一定要深入人心,當作心目中的十進位制。
/*
樹狀陣列
定義乙個a陣列乙個c陣列 記錄和
c[i]=a[i-2^k+1]+...a[i] k位i的二進位制右邊0的個數
計算的時候計算a[1]+..a[r]-(a[1]+...a[l])的和 即為從l開始到r的和
用處有兩個:
1.區間查詢
2.單點更新
樣例輸入:
51 2 3 4 5 (陣列元素)
2 4 (左區間和右區間)
輸出:9 (左右區間元素和)
*/#include
#include
#include
#include
#include
#include
using
namespace
std;
int a[1000],c[1000];
int n;
int lowbit(int i)
//這樣就可以直接算出2^k(k是2進製i中右邊0的個數)
void change(int i,int x)
}int getsum(int x)
return sum;
}int main()
int l;int r;
scanf("%d%d",&l,&r);
//cout/cout
<1)
0;}
更新元素計算
/*
樹狀陣列 更新元素再求和
(更新陣列中的元素 求左右區間內的元素和)
樣例輸入:
51 2 3 4 5 (陣列元素)
2 4 (左區間和右區間)
1 (更新一組)
2 5(把二換成5)
輸出:12 (左右區間元素和)
*/#include
#include
#include
#include
#include
#include
using
namespace
std;
int a[1000],c[1000];//乙個a陣列 乙個c陣列
int n;
int lowbit(int i)
//這樣就可以直接算出2^k(k是2進製i中右邊0的個數)
void change(int i,int x)
}void deal(int i,int x)
}int getsum(int x)
return sum;
}int main()
int l;int r;
scanf("%d%d",&l,&r);
int m;
scanf("%d",&m);//更新元素的組數
for(int i=1;i<=m;i++)
//cout/cout
<1)
0;}
樹狀陣列求逆序對可見此網頁
/*樣例5
1 5 2 4 3
輸出 4
*/#include
#include
#include
#include
#include
#include
using
namespace
std;
int c[100010];
struct nodea[100010];
int n;
int lowbit(int i)
void update(int i)
}int getsum(int x)
return sum;
}bool cmp(node xx,node yy)
sort(a+1,a+1+n,cmp);
//排序:離散化 如果a[i].v是10000000 那麼c的記憶體就要到1000000 但是排序以後再找逆序對在記憶體和時間上更優
for(int i=1;i<=n;i++)
cout
0;}
學習筆記 樹狀陣列
以下 為樹狀陣列最常用的幾個操作 1.low bi t mathrm lowbit function lowbit x longint int64 begin exit x and x end 2.單點修改 procedure replace x,y int64 var i int64 begin ...
樹狀陣列學習筆記
在學習完了線段樹後,聽說樹狀陣列能寫的題,線段樹都能做,所以一直沒有詳細的學習樹狀陣列 直到碰到了一道卡線段樹的題目,因為線段樹運用了很多遞迴,所以常數比較大,容易被卡 現在總結一下樹狀陣列 1 樹狀陣列個人認為就是字首和演變而來的 2 單點更新 當你要更新某個點的值時,你要從下面到上面依次更新過去...
樹狀陣列學習筆記
樹狀陣列 binary index tree,bit 也是很多人心中最簡潔優美的資料結構之一。最簡單的樹狀陣列支援兩種操作,時間複雜度均為 當然,樹狀陣列能維護的不侷限於加法,支援的操作也不止這兩種,甚至有大佬能用樹狀陣列實現平衡樹,但這篇筆記不會深入討論 因為我也還不是很懂 回顧一下,我們說,我們...