前缀和算法解决静态的数组的前缀和
树状数组算法可以解决动态数组的前缀和
前缀和–题目连接
前缀和暴力解法:(TEL)
#include<iostream>
using namespace std;
const int N=100000;
int a[N+10];
int s[N+10];
int main(){
int n,m;
cin>>n>>m;
s[0]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
while(m--){
int l,r;
int res=0;
cin>>l>>r;
for(int i=l;i<=r;i++){
res+=a[i];
}
cout<<res<<endl;
}
return 0;
}
前缀和解法(AC):
#include<iostream>
using namespace std;
const int N=100000;
int a[N+10];
int s[N+10];
int main(){
int n,m;
cin>>n>>m;
s[0]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
s[i]=s[i-1]+a[i];
}
while(m--){
int l,r;
cin>>l>>r;
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1000;
const int Q=200000;
int a[N+10][N+10];
int s[N+10][N+10];
int n,m,q;
int cnt=1;
int qq[Q];
int main(){
cin>> n >> m >> q;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
s[i][j]=s[i][j-1]+s[i-1][j]-s[i-1][j-1]+a[i][j];
}
}
while(q--){
int x1,y1,x2,y2;
cin>>x1>>y1>>x2>>y2;
qq[cnt++]=s[x2][y2]+s[x1-1][y1-1]-s[x2][y1-1]-s[x1-1][y2];
}
for(int i=1;i<=cnt-1;i++){
cout<<qq[i]<<endl;
}
return 0;
}
树状数组–裸题
动态求连续区间和以及插入数–题目链接
树状数组解:
#include<iostream>
using namespace std;
const int N=100000+10;
int n,m;
int a[N];
int tre[N];
int lowbit(int key){
return key & -key;
}
void add(int index, int key){
for(int i=index;i<=n;i+=lowbit(i)){
tre[i]+=key;
}
}
int query(int key){
int res=0;
for(int i=key;i;i-=lowbit(i)){
res+=tre[i];
}
return res;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
add(i,a[i]);
}
while(m--){
int a1,b,c;
cin>>a1>>b>>c;
if(!a1){
cout<<query(c)-query(b-1)<<endl;
}else{
add(b,c);
}
}
return 0;
}
线段树解:
#include<iostream>
using namespace std;
const int N=100000 +10;
int n,m;
int W[N];
struct Node{
int l,r;
int sum;
}tr[N*4];
void pushup(int u){
tr[u].sum=tr[u<<1].sum + tr[u<<1 | 1].sum;
}
void build(int u, int l, int r){
if(l == r) tr[u]={l,r,W[r]};
else{
tr[u]={l,r};
//除以 2 下取整
int mid= (l + r) >> 1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
pushup(u);
}
}
int query(int u, int l, int r){
if(tr[u].l>=l && tr[u].r<=r){
return tr[u].sum;
}else{
int mid=(tr[u].l+tr[u].r)>>1;
int sum=0;
if(l<=mid)
sum=query(u<<1,l,r);
if(r>mid)
sum+=query(u<<1|1,l,r);
return sum;
}
}
void modify(int u, int x ,int v){
if(tr[u].l==tr[u].r) tr[u].sum+=v;
else{
int mid=((tr[u].l+tr[u].r)>>1);
if(x<=mid) modify(u<<1,x,v);
else{
modify(u<<1|1,x,v);
}
pushup(u);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>W[i];
}
build(1,1,n);
int k,a,b;
while(m--){
cin>>k>>a>>b;
if(k==0)
cout<<query(1,a,b)<<endl;
else
modify(1,a,b);
}
return 0;
}