我們都知道樹狀陣列一般有兩種形式
1.最為傳統的版本,支援區間求和,單點修改
2.差分樹狀陣列 支援區間修改,單點查詢
而高階版樹狀陣列 可支援 區間求和,區間修改
其原理是:
設tree[i]=a[i]-a[i-1](差分),那麼容易得到:
tree[1]+tree[2]+……+tree[i]=a[i]這個公式
維護tree陣列即可以實現區間修改了。
接下來是區間查詢的實現問題
我們已經推出了乙個公式:
tree[1]+tree[2]+……tree[i]=a[i]
那麼,對於1到r的區間和,即為:
a[1]+a[2]+……+a[r-1]+a[r]
//用上方公式推導得出
=tree[1]+(tree[1]+tree[2])+……+(tree[1]+……+tree[r])
//根據加法交換律與結合律:
=(tree[1]*(r))+(tree[2]*(r-1))+……(tree[r]*1)
//那麼:
=r*(tree[1]+tree[2]+……+tree[r])-(tree[1]*0+tree[2]*1+……+tree[r]*(r-1))
看到這裡,是不是已經很清晰了呢?
對於a的樹狀陣列(差分)tree,建立乙個新的樹狀陣列tree1使得:
tree1[i]=tree[i]*(i-1)
之後,x到y的區間和即為:
(y*query(tree,y)-(x-1)*query(tree,x-1))-(query(tree1,y)-query(tree1,x-1))
p3372 【模板】線段樹 1
這種樹狀陣列可以實現線段樹的某些功能
#include#define rg register
#define inf 2147483647
#define min(a,b) (ab?a:b)
#define ll long long
#define maxn 100005
const double eps=1e-8;
using namespace std;
inline ll read()
while(ch>=48&&ch<=57)
return s*w;
}inline void write(ll x)
ll n,m;
ll tree[maxn],tree1[maxn];
inline ll lb(ll x)
inline void add(ll *tree,ll x,ll k)
}inline ll query(ll *tree,ll x)
return ans;
}int main()
for(rg ll i=1;i<=m;i++)
else if(x==2)
}return 0;
}
樹狀陣列高階
csdn同步 前置知識 下面我們考慮區間修改。一開始我們維護的是部分字首和,但是現在,區間修改顯然不能用字首和有關的做法。單區間修改用差分就夠了。但是這裡有修改,考慮將差分和樹狀陣列結合。令 c 為 a 的差分,維護 a 的區間修改與區間和即可,這樣 a 就是 c 的字首和了。那麼區間修改只需要改 ...
樹狀陣列 演算法高階專題
lowbit i i i 或者i i i i 1 9 and 1 1 要點 乙個數i對應二進位制表示未尾0的個數為k,那麼他管轄的範圍為 從i到左邊i 2 k 1的2 k 個元素。如 i 6 110 k 1 6管轄的範圍為 c 5 a 5 a 6 2 1 管2個。2 求前n個元素的和,n的二進位制的...
「高階」資料結構 樹狀陣列!
最簡單的樹狀陣列就是這樣的 void add int p,int x int ask int p int range ask int l,int r 通過 差分 就是記錄陣列中每個元素與前乙個元素的差 可以把這個問題轉化為問題1。設原陣列為a i 設陣列d i a i a i 1 a 0 0 則 a...