树状数组:动态前缀和,维护前i个点的贡献(可以维护信息线段树一类)
整体二分+树状数组:本质上说是利用分治来解决问题,树状数组用来维护贡献;一般流程为根据答案分流:询问+信息
树状数组模板:
//区间修改+点查
#define lowbit(x) (x&-x)
struct BIT{
vector<i64>s;
void init(int n){s.resize(n+1,0);}
void add(int x,i64 k, int mx){
while(x<=mx)s[x]+=k,x+=lowbit(x);
}
i64 query(int x){
i64 t=0;
while(x)t+=s[x],x-=lowbit(x);
return t;
}
}T;
//区间修改+区间查询
#define lowbit(x) (x&-x)
struct BIT{
vector<i64>s;
vector<i64>s1;
void init(int n){s.resize(n+1,0);s1.resize(n+1,0);}
void add(int x,i64 k){
while(x<=n)s[x]+=k,x+=lowbit(x);
}
void add1(int x,i64 k){
while(x<=n)s1[x]+=k,x+=lowbit(x);
}
i64 query(int x){
i64 t=0;
while(x)t+=s[x],x-=lowbit(x);
return t;
}
i64 query1(int x){
i64 t=0;
while(x)t+=s1[x],x-=lowbit(x);
return t;
}
i64 query(int l,int r){
return query(r)*r-query1(r)-query(l-1)*(l-1)+query1(l-1);
}
}T;
//二维
#define lowbit(x) (x&-x)
struct BIT{
vector<vector<int>>s;
void init(int n, int m){s.resize(n + 1, vector<int>(m + 1, 0));}
void add(int x,int y,int k){
for(int i=x; i<=n; i+=lowbit(i)){
for(int j=y; j<=m; j+=lowbit(j)){
s[i][j]+=k;
}
}
}
int query(int x, int y){
int t=0;
for(int i=x; i>0; i-=lowbit(i)){
for(int j=y; j>0; j-=lowbit(j)){
t+=s[i][j];
}
}
return t;
}
}T;
训练题目:
[USACO17JAN] Promotion Counting P - 洛谷
Matrix - POJ 2155 - Virtual Judge
https://vjudge.net/problem/Gym-103861L