树状数组小板子

树状数组的单点修改,区间修改,单点查询,区间查询

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 ;
}

区间修改区间查询

\sum_{i = 1}^{x}\sum_{j = 1}^{y}\sum_{h = 1}^{i}\sum_{k = 1}^{j}d[h][k]             

统计出现了多少次得到:\sum_{i = 1}^{x}\sum_{j = 1}^{y}d[i][j] * (x + 1 - i) * (y + 1 - j)

拆开得到:

(x + 1) * (y + 1) * \sum_{i = 1}^{x}\sum_{j = 1}^{y}d[i][j] - (y + 1) * \sum_{i = 1}^{x}\sum_{j = 1}^{y}d[i][j] * i - (x + 1) * \sum_{i = 1}^{x}\sum_{j = 1}^{y}d[i][j] * j + \sum_{i = 1}^{x}\sum_{j = 1}^{y}d[i][j] * i * j

所以我们需要维护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 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值