树状数组的单点修改,区间修改,单点查询,区间查询
lowbit:
int lowbit(int x) {
return x & -x ;
}
struct Fenwick {
void add(int pos, int w) { //单点修改
for ( ; pos <= n ; pos += lowbit(pos))
info[pos] += w ;
}
ll ask(int pos) { //单点询问
ll ans{0} ;
for ( ; pos ; pos -= lowbit(pos))
ans += info[pos] ;
return ans ;
}
ll range(int l, int r) { //区间查询
return ask(r) - ask(l - 1 ) ;
}
} bt;
int l, r, w ; //区间修改
cin >> l >> r >> w ;
bt.add(l, w) ;
bt.add(r + 1, -w) ;
区间修改&区间查询
#include <bits/stdc++.h>
using namespace std ;
int n, q ;
using ll = long long ;
const int N = 1e6 + 8 ;
ll info1[N] ;
ll info2[N] ;
ll num[N] ;
ll lowbit(ll x) {
return x & -x ;
}
struct Fenwick {
void add(ll pos, ll w) {
for ( ; pos <= n ; pos += lowbit(pos)) {
info1[pos] += w;
}
}
void ad(ll pos, ll w ) {
for ( ; pos <= n ; pos += lowbit(pos )) {
info2[pos] += w ;
}
}
ll ask(ll pos) {
ll ans = 0 ;
for ( ; pos ; pos -= lowbit(pos))
ans += info1[pos] ;
return ans ;
}
ll as(ll pos ) {
ll ans = 0 ;
for ( ; pos ; pos -= lowbit(pos))
ans += info2[pos] ;
return ans ;
}
ll solve(ll pos) {
return (pos + 1) * ask(pos) - as(pos) ;
}
ll range(ll l, ll r) {
return solve(r) - solve(l - 1) ;
}
} bt;
int main() {
cin >> n >> q ;
for (int i = 1 ; i <= n; i ++) {
cin >> num[i] ;
bt.add(i, num[i] - num[i - 1]) ;
bt.ad(i, i * (num[i] - num[i - 1 ])) ;
}
while (q --) {
ll op ;
cin >> op ;
if (op == 1) {
ll l, r, w ;
cin >> l >> r >> w ;
bt.add(l, w) ;
bt.add(r + 1, -w) ;
bt.ad(l, w * l) ;
bt.ad(r + 1, - (r + 1) * w) ;
} else {
ll l, r ;
cin >> l >> r ;
cout << bt.range(l, r) << '\n' ;
}
}
return 0 ;
}
二维树状数组
单点修改 区间查询
#include <bits/stdc++.h>
using namespace std ;
const int N = 1e4 + 8 ;
using ll = long long ;
ll mp[N][N] ;
ll info[N][N] ;
int n, m ;
int lowbit(int x) {
return x & -x ;
}
struct Fenwick {
void add(int x, int y, int w) {
for (int i = x ; i <= n ; i += lowbit(i))
for ( int j = y ; j <= m ; j += lowbit(j))
info[i][j] += w ;
}
ll ask(int x, int y) {
ll ans = 0 ;
for (int i = x ; i >= 1 ; i -= lowbit(i)) {
for (int j = y ; j >= 1 ; j -= lowbit(j))
ans += info[i][j] ;
}
return ans ;
}
} bt;
int main() {
cin >> n >> m ;
int x ;
while (cin >> x ) {
if (x == 1) {
int x, y, w ;
cin >> x >> y >> w ;
bt.add(x, y, w ) ;
} else {
int x1, y1, x2, y2 ;
cin >> x1 >> y1 >> x2 >> y2 ;
cout << bt.ask(x2, y2) + bt.ask(x1 - 1, y1 - 1) - bt.ask(x2, y1 - 1) - bt.ask(x1 - 1, y2) << '\n' ;
}
}
return 0 ;
}
区间修改 单点查询
#include <bits/stdc++.h>
using namespace std ;
const int N = 1e4 + 8 ;
using ll = long long ;
int n, m ;
ll info[N][N] ;
int lowbit(int x) {
return x & -x ;
}
struct Fenwick {
ll ask(int x, int y) {
ll ans = 0 ;
for (int i = x ; i >= 1 ; i -= lowbit(i))
for (int j = y ; j >= 1 ; j -= lowbit(j))
ans += info[i][j] ;
return ans ;
}
void add(int x, int y, int w) {
for (int i = x ; i <= n ; i += lowbit(i) )
for (int j = y ; j <= m ; j += lowbit(j))
info[i][j] += w ;
}
} bt;
int main() {
cin >> n >> m ;
int op ;
while (cin >> op) {
if (op == 1) {
int x1, y1, x2, y2, val ;
cin >> x1 >> y1 >> x2 >> y2 >> val ;
bt.add(x2 + 1, y2 + 1, val) ;
bt.add(x1, y2 + 1, -val) ;
bt.add(x2 + 1, y1, -val) ;
bt.add(x1, y1, val) ;
} else {
int x, y ;
cin >> x >> y ;
cout << bt.ask(x, y) << '\n' ;
}
}
return 0 ;
}
区间修改区间查询
统计出现了多少次得到:
拆开得到:
所以我们需要维护d[i][j],d[i][j] * i,d[i][j] * j,d[i][j] * i * j 这四个数组
#include <bits/stdc++.h>
using namespace std ;
const int N = 2050 ;
using ll = long long ;
ll n, m ;
// 需要用四个数组来进行维护
ll info1[N][N] ; //
ll info2[N][N] ; // i
ll info3[N][N] ; // j
ll info4[N][N] ; // i * j
ll lowbit(ll x) {
return x & -x ;
}
struct Fenwick {
ll ask(ll x, ll y) {
ll ans = 0 ;
for (int i = x ; i >= 1 ; i -= lowbit(i))
for (int j = y ; j >= 1 ; j -= lowbit(j))
ans += (x + 1) * (y + 1) * info1[i][j] - (y + 1) * info2[i][j] - (x + 1) * info3[i][j] + info4[i][j];
return ans ;
}
void add(ll x, ll y, ll w) {
for (int i = x ; i <= n ; i += lowbit(i) )
for (int j = y ; j <= m ; j += lowbit(j)) {
info1[i][j] += w ;
info2[i][j] += x * w ;
info3[i][j] += y * w ;
info4[i][j] += x * y * w ;
}
}
ll out(ll x1, ll y1, ll x2, ll y2) {
return ask(x2, y2) + ask(x1 - 1, y1 - 1 ) - ask(x1 - 1, y2) - ask(x2, y1 - 1 ) ;
}
} bt;
int main() {
cin >> n >> m ;
int op ;
while (cin >> op) {
if (op == 1) {
ll x1, y1, x2, y2, val ;
cin >> x1 >> y1 >> x2 >> y2 >> val ;
bt.add(x2 + 1, y2 + 1, val) ;
bt.add(x1, y2 + 1, -val) ;
bt.add(x2 + 1, y1, -val) ;
bt.add(x1, y1, val) ;
} else {
ll x1, y1, x2, y2 ;
cin >> x1 >> y1 >> x2 >> y2 ;
cout << bt.out(x1, y1, x2, y2) << '\n' ;
}
}
return 0 ;
}