樹狀陣列之————區間修改+區間查詢
樹狀陣列的工作是 對一組資料進行快速修改查詢操作區間修改+區間查詢最基本的功能是 單點修改+區間查詢。
然後厲害的是 區間修改+單點查詢(用陣列del[i]表示原陣列a[i]-a[i-1]的值)
更厲害的來了。。。
用陣列del[i]記錄原陣列a[i]與前一項和,即del[i]=a[i]-a[i-1]求陣列a的前n項和就是:
s(n) = a[1]+a[2]+...a[n]
= del[1] + (del[1]+del[2]) + .... + (del[1]+del[2]+....del[n])
= n*del[1] + (n-1)*del[2] + .... + 1*del[n]
= (n+1 -1)*del[1] + (n+1 -2)*del[2] + .... + (n+1 -n)*del[n]
= (n+1)*(del[1]+del[2]+ ... +del[n]) - (1*del[1] + 2*del[2] + ... + n*del[n])
= (n+1)*sum(del[i], 1<=i<=n) - sum(i*del[i], 1<=i<=n)
其實只需要求出(n+1)*sum(del[i]) ,和sum(i*del[i], 1<=i<=n),相減即可
所以就用兩個樹狀陣列共同維護
用陣列c1[i]維護del[i]
用陣列c2[i]維護i*del[i]
對陣列進行操作時,用時更新這兩個陣列即可。查詢時,用上面推導的公式
對於那兩個查詢和修改函式不變,依然沿用最老套的模板
**實現詳見例題:1082 線段樹練習 3
【**】:
#include#includeusing namespace std;
typedef long long ll;
ll a[202020];
ll del[202020];
ll c1[202020];//維護del
ll c2[202020];//維護x*del[x]
ll n;
void add(ll *c,ll k,ll num)
ll read(ll *c,ll k)//查詢區間1~k
ll sum(ll k)
int main()
ll q;cin>>q;
while(q--)
else
{ ll a,b;cin>>a>>b;
ll sumr=sum(b);
ll suml=sum(a-1);
cout<
樹狀陣列 區間修改,區間查詢
也許更好的閱讀體驗 好東西,以後可以不打線段樹了 本篇假定讀者都會最基礎的兩種樹狀陣列,即區改單查和單改區查 思考如何維護乙個區間的值,想到了差分 對乙個差分陣列做一次字首和可以得到每個位置的值 再對每個位置累加一下就是乙個區間的值 公式化的講,就是 設差分陣列為 c 則每個位置的值 val i s...
樹狀陣列區間修改區間查詢
題面 首先,我們要推乙個柿子。displaystyle sum a i 把a i 用差分陣列表示出來,就可以寫成 displaystyle sum sum d i 我們考慮一下,每個d i 出現的次數是一定的。那我們可以換一下列舉順序,先列舉d i 在列舉他出現的次數,就可以變成 displayst...
樹狀陣列高階 區間修改 區間查詢
區間修改與區間查詢 今天老糊塗了,樹狀陣列忘記了,基本的只要單點修改 區間查詢功能,如果要進行區間加操作,需要把樹狀陣列進行改造。我們首先來回顧樹狀陣列的功能 lowbit x x 返回二進位制最低位 1的值 比如 x 1010 那麼lowbit值為2 x lowbit x 把最後一位二進位制最低位...