樹狀數組區間修改加區間查詢

其實以前在K大數查詢中就已經用到了,只是一直沒有說明
因此今天就來補個欠帳。
感受單點修改、區間查詢和區間修改、單點查詢沒什麼必要講,這裏就只講區間修改、區間查詢(其實也不難)。
設原數組第\(i\)位的值爲\(a_i\)\(d_i=a_i-a_{i-1}\),則有(這裏認爲\(a_0=0\)):
\[a_x=\sum_{i=1}^x d_i\]
因此有:
\[\sum_{i=1}^x a_i= \sum_{i=1}^x \sum_{j=1}^i d_j =\sum_{i=1}^x(x-i+1)d_i\]
因而咱們獲得了:
\[\sum_{i=1}^x a_i=(x+1)\sum_{i=1}^x d_i-\sum_{i=1}^x d_i \times i\]
因而咱們把原數組差分後維護兩個樹狀數組,一個維護\(d_i\),一個維護\(d_i \times i\)
這樣區間求和時能夠在兩個樹狀數組中查詢獲得前綴和,區間修改時就是差分數組的修改,每次修改兩個點便可。
具體代碼以下:html

void add(int x,int y){for(int i=x;i<=n;i+=i&(-i)) c1[i]+=y,c2[i]+=(long long)x*y;}//給差分數組中的位置x加上y
long long sum(int x){//查詢前x項的和
    long long ans(0);
    for(int i=x;i;i-=i&(-i)) ans+=(x+1)*c1[i]-c2[i];
    return ans;
}

其中\(c{1_i}\)維護的是\(d_i\)\(c{2_i}\)維護的是\(d_i\times i\)
比線段樹好寫多了是不?數組

相關文章
相關標籤/搜索