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


其實之前在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\)
這樣區間求和時可以在兩個樹狀數組中查詢得到前綴和,區間修改時就是差分數組的修改,每次修改兩個點即可。
具體代碼如下:

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\)
比線段樹好寫多了是不?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM