【模板】樹狀數組上的差分數組
阿新 • • 發佈:2019-01-23
string cstring 能夠 name 證明 spa data 形式 pre
數據差分化是一個很神仙也很實用的方法。
具體操作就是將一個數化為多個項的和的形式,這些我們產生的項多為g(x)=f(i)-f(i-1)一類形式,這樣可以錯位相消去,十分巧妙。
數據差分化有以下神仙之處:
通過差分數據得到原數據g(x):十分顯然,g(x)=f(1)+f(2)+f(3)+……+f(x) , ( f(0)=0 )。證明略。
改變區間[ l , r ]的值,只需要進行g(l)=g(l)+k, g(r+1)=g(r+1)-k這樣的操作就行了。原因是中間的項全部通過加減抵消了那個加入的k。
因此,維護一個差分化的數據,需要一種能夠高效訪問區間[ l , r ]的數據結構,那這種數據結構還有什麽呢?當然是
線段樹&樹狀數組
對不起我太弱了導致只知道這兩個
附上代碼(樹狀數組( 2 ) 的)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; inline ll qr(){ char c=getchar(); ll x=0,q=1; while(c<48||c>57) q=c==45?-1:q,c=getchar(); while(c>=48&&c<=57) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return q*x; } const int maxn=500000+15; ll data[maxn]; #define lw(x) (x&(-x)) int n,m; #define RP(t,a,b) for(int t=(a),edd=(b);t<=edd;t++) inline void add(int pos,int dataq){ int t=pos; while(t<=n){ data[t]+=dataq; t+=lw(t); } return; } inline ll ask(int x){ ll ret=0; int pos=x; while(pos){ ret+=data[pos]; pos-=lw(pos); } return ret; } int templ,last; int t1,t2,t3,t4; int main(){ //freopen("in.in","r",stdin); //freopen("out.out","w",stdout); n=qr(); m=qr(); RP(t,1,n){ templ=qr(); add(t,templ-last); last=templ; } RP(t,1,m){ t1=qr(); if(t1==1){ t2=qr(); t3=qr(); t4=qr(); add(t2,t4); add(t3+1,-t4); } else{ t2=qr(); cout<<ask(t2)<<endl; } } return 0; }
此類數據結構,應靈活應用,來達到一些神仙的十分之一的水平。
再次感嘆我真是太弱了
【模板】樹狀數組上的差分數組