一:单点修改区间求和,最裸的题
题目链接:https://www.luogu.com.cn/problem/P3374
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=500000+10; ll a[maxn],c[maxn]; int n,m,i,j,q,x,y,k; void add(int i,int x){ while (i<=n){ c[i]+=x;i+=(i&-i); } } ll sum(int i){ ll res=0; while (i>0){ res+=c[i];i-=(i&-i); } return res; } int main(){ std::ios::sync_with_stdio(false); cin>>n>>m; for (i=1;i<=n;i++){ cin>>a[i];add(i,a[i]); } for (i=1;i<=m;i++){ cin>>q; if (q==1){ cin>>x>>k;add(x,k); } if (q==2){ cin>>x>>y;cout<<sum(y)-sum(x-1)<<endl; } } return 0; }
二:区间修改单点求和
题目链接:https://www.luogu.com.cn/problem/P3368
利用差分转化为第一种情况即可
#include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=500000+10; ll a[maxn],c[maxn]; int n,m,i,j,k,q,x,y; void add(int i,int x){ while (i<=n){ c[i]+=x;i+=(i&-i); } } ll sum(ll i){ ll res=0; while (i>0){ res+=c[i];i-=(i&-i); } return res; } int main(){ std::ios::sync_with_stdio(false); cin>>n>>m; for (i=1;i<=n;i++){ cin>>a[i]; add(i,a[i]);add(i+1,-a[i]); } for (i=1;i<=m;i++){ cin>>q; if (q==1){ cin>>x>>y>>k; add(x,k);add(y+1,-k); } if (q==2){ cin>>x; cout<<sum(x)<<endl; } } return 0; }
三:求逆序对
题目链接:https://vjudge.net/problem/POJ-2299
倒序扫描数组a,核心代码只有 ans+=ask(a[i]-1); add(a[i],1)。有时数据大了要离散化
#include<cstdio> #include<algorithm> #include<cstring> #define ll long long using namespace std; const int N=500010; int c[N],a[N],x[N]; int n,i,j,k,m; int lowbit(int y) {return y&(-y);} void add(int x,int y) {while (x<=n){c[x]+=y; x+=lowbit(x);}} int ask(int x){ int res=0; while (x>0) {res+=c[x]; x-=lowbit(x);} return res; } int main(){ while (scanf("%d",&n)&&(n!=0)){ for (i=1;i<=n;i++) {scanf("%d",&a[i]); x[i]=a[i]; c[i]=0;} sort(x+1,x+n+1); for (i=1;i<=n;i++) a[i]=lower_bound(x+1,x+n+1,a[i])-x; ll ans=0; for (i=n;i>=1;i--){ ans+=ask(a[i]-1); add(a[i],1); } printf("%lld ",ans); } return 0; }
四:二维树状数组的单点修改,区间求和
题目链接:https://vjudge.net/problem/POJ-1195
模板题。但是有一个地方一开始写错了,就是询问区域和的式子,这个以后要注意
#include<cstdio> #include<cstring> using namespace std; const int N=1100; int c[N][N],s,I,x,y,a,l,b,r,t; int lowbit(int x){ return x&(-x);} void add(int u,int v,int d){ for (int i=u;i<=s;i+=lowbit(i)) for (int j=v;j<=s;j+=lowbit(j)) c[i][j]+=d; } int ask(int u,int v){ int res=0; for (int i=u;i>0;i-=lowbit(i)) for (int j=v;j>0;j-=lowbit(j)) res+=c[i][j]; return res; } int main(){ scanf("%d",&I); while (I!=3){ if (I==0){scanf("%d",&s); memset(c,0,sizeof(c));} if (I==1){ scanf("%d%d%d",&x,&y,&a); x++;y++; add(x,y,a); } if (I==2){ scanf("%d%d%d%d",&l,&b,&r,&t); l++;b++;r++;t++; printf("%d ",ask(r,t)-ask(r,b-1)-ask(l-1,t)+ask(l-1,b-1)); } scanf("%d",&I); } return 0; }