C81【模板】树状数组 点修+区查 区修+点查

C81【模板】树状数组 点修+区查 区修+点查_哔哩哔哩_bilibili

 

树状数组 - OI Wiki

树状数组是一种支持 单点加 和 区间查 的,代码量小的数据结构.

普通树状数组维护的信息及运算要满足 结合律 且 可差分,如加法(和)、乘法(积)、异或等.

树状数组能解决的问题是线段树能解决的问题的子集.树状数组代码短,常数小.

在差分数组和辅助数组的帮助下,树状数组还可解决更强的 区间加 单点查 和 区间加 区间和 问题.

树状数组的拿手绝活——“点加+区查(区间和)” 和 “区加(点差分)+点查(前缀和)”

 

P3374 【模板】树状数组 1 - 洛谷
// 树状数组 点加+区和 O(nlogn)
#include<bits/stdc++.h>
using namespace std;

const int N=500010;
int n,m;

struct BIT{
  int c[N]; //区间和
  void upd(int x,int w){ //向后修
    for(;x<=n;x+=x&-x) c[x]+=w;
  }
  int ask(int x){ //向前查,前缀和
    int s=0;
    for(;x;x-=x&-x) s+=c[x];
    return s;
  }
}B;
int main(){
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  cin>>n>>m;
  for(int i=1,k;i<=n;i++) cin>>k, B.upd(i,k); //初值
  for(int i=1,op,x,y,k;i<=m;i++){
    cin>>op>>x;
    if(op==1) cin>>k, B.upd(x,k); //点修
    else cin>>y, cout<<B.ask(y)-B.ask(x-1)<<"\n"; //区查
  }
}

 

P3368 【模板】树状数组 2 - 洛谷

// 树状数组 区加(点差分)+前缀和 O(nlogn)
#include<bits/stdc++.h>
using namespace std;

const int N=500010;
int n,m,a[N];

struct BIT{
  int c[N]; //差分的区间和
  void upd(int x,int w){
    for(;x<=n;x+=x&-x) c[x]+=w;
  }
  void upd(int x,int y,int w){
    upd(x,w); upd(y,-w); //点差分
  }
  int ask(int x){ //前缀和
    int s=a[x]; //初值
    for(;x;x-=x&-x) s+=c[x];
    return s;
  }
}B;
int main(){
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  cin>>n>>m;
  for(int i=1;i<=n;i++) cin>>a[i];
  for(int i=1,op,x,y,k; i<=m; i++){
    cin>>op>>x;
    if(op==1){
      cin>>y>>k;
      B.upd(x,y+1,k); //区修
    }
    else cout<<B.ask(x)<<"\n"; //点查
  }
}

 

posted @ 2023-12-28 17:16  董晓  阅读(1176)  评论(0)    收藏  举报