樹狀陣列 區間修改區間查詢
阿新 • • 發佈:2019-02-05
在這道題因為資料型別卡了我1個多小時之後,我終於把它幹掉了(洛谷3372也可以用這道題的程式碼過,複製過去改一下讀入順序就行,目測codevs的資料比較毒瘤)
樹狀陣列 區間修改+區間查詢
實在是喜歡樹狀陣列啊!好理解,更重要是好寫啊!這次寫寫區間修改區間查詢哈
首先還是上次區間修改單點查詢用過的差分思想,我們先搞一個c陣列作為差分陣列(不懂的去看我的上一個部落格好了,實在懶得列表了)
簡單可證,
那麼可以得到以下式子
a[1]+a[2]+...+a[i]
=c[1]+(c[1]+c[2])+...+(c[1]+c[2]+...+c[i])
=i*c[1]+(i-1)*c[2]+...+c[i]
=i*(c[1]+c[2]+...+c[i])-1*c[2]-...-(i-1)*c[i]
於是,我們再搞一個數組c1
那之前的式子就可以表示為
然後再搞兩個樹狀陣列來分別維護一下c陣列和c1陣列的區間和就ok了
下面貼的是codevs1082的AC程式碼,這是一道線段樹的模板題,裸題
(這裡b陣列是c的樹狀陣列,bb陣列是c1陣列的樹狀陣列,然後因為懶,所以函式直接複製了一下,不太美觀哈)
#include<bits/stdc++.h> using namespace std; long long n,m,a[200010],b[200010],c[200010],bb[200010],c1[200010]; long long lowbit(long long x) { return x&-x; } void modify(int x,long long y) { for (int i=x;i<=n;i+=lowbit(i)) b[i]+=y; } long long query(long long x) { long long ans=0; for (int i=x;i>0;i-=lowbit(i)) ans+=b[i]; return ans; } void modifyy(long x,long long y) { for (int i=x;i<=n;i+=lowbit(i)) bb[i]+=y; } long long queryy(long long x) { long long ans=0; for (int i=x;i>0;i-=lowbit(i)) ans+=bb[i]; return ans; } int main() { cin>>n; for (int i=1;i<=n;i++) { cin>>a[i]; c[i]=a[i]-a[i-1]; c1[i]=(i-1)*c[i]; } for (int i=1;i<=n;i++) modify(i,c[i]); for (int i=1;i<=n;i++) modifyy(i,c1[i]); cin>>m; for (int i=1;i<=m;i++) { long long p; cin>>p; if (p==1) { long long xx,yy,zz; cin>>xx>>yy>>zz; modify(xx,zz); modify(yy+1,-zz); modifyy(xx,(xx-1)*zz); modifyy(yy+1,-yy*zz); } if (p==2) { long long xx,yy,ss; cin>>xx>>yy; ss=(yy*query(yy)-queryy(yy))-((xx-1)*query(xx-1)-queryy(xx-1)); cout<<ss<<endl; } } return 0; }
友情提醒,做這道題的時候一定要開longlong,這個事情卡了我1個多小時%%%%
我寫程式碼的時候一順手就寫了個cin cout……這道題沒啥事,但平時還是要寫scanf的