日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ACM入门之【树状数组】

發(fā)布時間:2025/3/20 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ACM入门之【树状数组】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

樹狀數(shù)組和線段樹具有相似的功能,但他倆畢竟還有一些區(qū)別:樹狀數(shù)組能有的操作,線段樹一定有;線段樹有的操作,
樹狀數(shù)組不一定有。但是樹狀數(shù)組的代碼要比線段樹短,思維更清晰,速度也更快,在解決一些單點修改的問題時,樹狀數(shù)組是不二之選。


樹狀數(shù)組 數(shù)據(jù)結(jié)構(gòu)詳解與模板
它的各項操作的時間復(fù)雜度均為:O(logn)

常見的模型:

  • 單點修改,區(qū)間求和
  • 區(qū)間修改,單點求值
  • 區(qū)間修改,區(qū)間求值
  • 二維樹狀數(shù)組,單點修改,矩陣求值。
  • 二維樹狀數(shù)組, 區(qū)間修改 單點查詢。
  • 二維樹狀數(shù)組, 區(qū)間修改,區(qū)間查詢。

單點修改,區(qū)間求和模板

const int N=1e6+10; typedef long long int LL; LL tr[N],n; int lowbit(int x){return x&(-x);} void add(int u,int x)//u位置加x {for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=x; } LL query(int u)//求[1,u]的和 {LL sum=0;for(int i=u;i;i-=lowbit(i)) sum+=tr[i];return sum; }

區(qū)間修改,單點求值模板:

//基于差分的思想 const int N=1e6+10; typedef long long int LL; LL tr[N],a[N],n,m; int lowbit(int x){return x&(-x);} void add(int u,int x)//u位置加x {for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=x; } LL query(int u)//求點u的值 {LL sum=0;for(int i=u;i;i-=lowbit(i)) sum+=tr[i];return sum; } void init()//初始化差分?jǐn)?shù)列 {for(int i=1;i<=n;i++) add(i,a[i]-a[i-1]); } void solve(int l,int r,int x)//[l,r]加x {add(l,x),add(r+1,-x); }

區(qū)間修改,區(qū)間求值模板:

const int N=1e6+10; typedef long long int LL; LL tr1[N],tr2[N],a[N],n,m; LL lowbit(LL x){return x&(-x);} void add(LL tr[],LL u,LL c) {for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=c; } LL query(LL tr[],LL u) {LL sum=0;for(int i=u;i;i-=lowbit(i)) sum+=tr[i];return sum; } LL sum(LL u) {return 1ll*(u+1)*query(tr1,u)-query(tr2,u); } void init()//初始化 {for(int i=1;i<=n;i++){add(tr1,i,a[i]-a[i-1]);add(tr2,i,i*(a[i]-a[i-1]));} } void add_lr(LL l,LL r,LL c)//[l,r]區(qū)間內(nèi)加c {add(tr1,l,c),add(tr1,r+1,-c);add(tr2,l,l*c),add(tr2,r+1,-(r+1)*c); } LL query_lr(LL l,LL r)//查詢區(qū)間[l,r] {return sum(r)-sum(l-1); }

二維樹狀數(shù)組,單點修改,矩陣求值模板:

const int N=5050; typedef long long int LL; LL tr[N][N],n,m; int lowbit(int x){return x&(-x);} void add(int x,int y,int v)//[x,y]加v {for(int i=x;i<=n;i+=lowbit(i))for(int j=y;j<=m;j+=lowbit(j))tr[i][j]+=v; } LL query(int x,int y) {LL sum=0; for(int i=x;i;i-=lowbit(i))for(int j=y;j;j-=lowbit(j)) sum+=tr[i][j];return sum; } LL query_ans(int x,int y,int xx,int yy) //找[x,y][xx,yy]為左上角和右下角的矩陣的和 {return query(xx,yy)-query(xx,y-1)-query(x-1,yy)+query(x-1,y-1); }

二維樹狀數(shù)組, 區(qū)間修改 單點查詢模板:

const int N=5050; typedef long long int LL; LL tr[N][N],n,m; int lowbit(int x){return x&(-x);} void add(int x,int y,int v)//[x,y]加v {for(int i=x;i<=n;i+=lowbit(i))for(int j=y;j<=m;j+=lowbit(j))tr[i][j]+=v; } LL query(int x,int y)//單點查詢 {LL sum=0; for(int i=x;i;i-=lowbit(i))for(int j=y;j;j-=lowbit(j)) sum+=tr[i][j];return sum; } void add1(int x,int y,int xx,int yy,int k)//區(qū)間加 {add(x,y,k),add(xx+1,y,-k);add(x,yy+1,-k),add(xx+1,yy+1,k); }

二維樹狀數(shù)組, 區(qū)間修改,區(qū)間查詢模板:

typedef long long LL; const int N = 5000 + 10; LL t1[N][N],t2[N][N],t3[N][N],t4[N][N]; int n,m; int lowbit(int x) {return x & - x;} void add(int a, int b, int k) {for (int i = a; i <= n; i += lowbit(i)) {for (int j = b; j <= m; j += lowbit(j)) {t1[i][j] += k;t2[i][j] += k * a;t3[i][j] += k * b;t4[i][j] += k * a * b;}} } LL sum(int a, int b) {LL ans=0;for (int i=a;i;i-=lowbit(i))for (int j=b;j;j-=lowbit(j))ans+=t1[i][j]*((a+1)*(b+1))-t2[i][j]*(b+1)-t3[i][j]*(a+1)+t4[i][j];return ans; } void add1(int a,int b,int c,int d,int k) //[a,b][c,d]為左上角和右下角的矩陣所有值加k {add(a, b, k);add(c + 1, d + 1, k);add(a, d + 1, -k);add(c + 1, b, -k); } LL query_ans(int a,int b,int c,int d) //求區(qū)間[a,b],[c,d]為左上角和右下角的和 {return sum(a-1,b-1)+sum(c,d)-sum(a-1,d)-sum(c,b-1); }

總結(jié)

以上是生活随笔為你收集整理的ACM入门之【树状数组】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。