ACM入门之【树状数组习题】
生活随笔
收集整理的這篇文章主要介紹了
ACM入门之【树状数组习题】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目錄
- 130. 樹狀數組 1 :單點修改,區間查詢
- 131. 樹狀數組 2 :區間修改,單點查詢
- 132. 樹狀數組 3 :區間修改,區間查詢
- 133. 二維樹狀數組 1:單點修改,區間查詢
- 134. 二維樹狀數組 2:區間修改,單點查詢
- 135. 二維樹狀數組 3:區間修改,區間查詢
- P1908 逆序對
130. 樹狀數組 1 :單點修改,區間查詢
https://loj.ac/p/130
131. 樹狀數組 2 :區間修改,單點查詢
https://loj.ac/p/131
132. 樹狀數組 3 :區間修改,區間查詢
#include<bits/stdc++.h> using namespace std; 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]區間內加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)//查詢區間[l,r] {return sum(r)-sum(l-1); } int main(void) {cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];init();for(int i=0;i<m;i++){int op; cin>>op;if(op==1){LL l,r,c; cin>>l>>r>>c;add_lr(l,r,c);}else{LL l,r; cin>>l>>r;cout<<query_lr(l,r)<<endl;}}return 0; }133. 二維樹狀數組 1:單點修改,區間查詢
#include<bits/stdc++.h> using namespace std; 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); } int main(void) {cin>>n>>m;int op;while(cin>>op){if(op==1){int x,y,k; cin>>x>>y>>k;add(x,y,k);}else {int x,y,xx,yy; cin>>x>>y>>xx>>yy;cout<<query_ans(x,y,xx,yy)<<endl;}}return 0; }134. 二維樹狀數組 2:區間修改,單點查詢
#include<bits/stdc++.h> using namespace std; 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)//區間加 {add(x,y,k),add(xx+1,y,-k);add(x,yy+1,-k),add(xx+1,yy+1,k); } int main(void) {cin>>n>>m;int op; while(cin>>op){if(op==1){int x,y,xx,yy,c; cin>>x>>y>>xx>>yy>>c;add1(x,y,xx,yy,c);}else{int x,y; cin>>x>>y;cout<<query(x,y)<<endl;}}return 0; }135. 二維樹狀數組 3:區間修改,區間查詢
#include<bits/stdc++.h> using namespace std; 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) //求區間[a,b],[c,d]為左上角和右下角的和 {return sum(a-1,b-1)+sum(c,d)-sum(a-1,d)-sum(c,b-1); } int main() {scanf("%d%d",&n,&m);int op,a,b,c,d,k;while(~scanf("%d", &op)){if(op==1) {scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);add1(a,b,c,d,k);} else {scanf("%d%d%d%d",&a,&b,&c,&d);printf("%lld\n",query_ans(a,b,c,d));}}return 0; }P1908 逆序對
#include<bits/stdc++.h> using namespace std; const int N=1e6+10; typedef long long int LL; int a[N],tr[N],n; vector<int>ve; int lowbit(int x){return x&(-x);} void add(int u,int v) {for(int i=u;i<=n;i+=lowbit(i)) tr[i]+=v; } LL query(int u) {LL sum=0;for(int i=u;i;i-=lowbit(i)) sum+=tr[i];return sum; } int main(void) {cin>>n;for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) ve.push_back(a[i]);sort(ve.begin(),ve.end());ve.erase(unique(ve.begin(),ve.end()),ve.end());LL ans=0;for(int i=1;i<=n;i++){int l=upper_bound(ve.begin(),ve.end(),a[i])-ve.begin();//找到第一個大于a[i]的下標,從0開始ans+=query(n)-query(l);add(l,1);}cout<<ans;return 0; } 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的ACM入门之【树状数组习题】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: A. Powered Addition【
- 下一篇: ACM入门之【树状数组】