IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 一维二维树状数组模板题加题解 -> 正文阅读

[C++知识库]一维二维树状数组模板题加题解

一维:

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

题目描述

这是一道模板题。

给定数列a1?,a2?,…,an?,你需要依次进行?q?个操作,操作有两类:

  • 1 i x:给定?i,x,将 ai??加上?x;
  • 2 l r:给定?l,r,求?∑i=lr?ai??的值(换言之,求 al?+al+1?+?+ar??的值)。

输入格式

第一行包含?2?个正整数?n,q,表示数列长度和询问个数。保证 1≤n,q≤1e6。
第二行?n?个整数?a1?,a2?,…,an?,表示初始数列。保证?∣ai?∣≤1e6。
接下来?q?行,每行一个操作,为以下两种之一:

  • 1 i x:给定?i,x,将?a[i]?加上?x;
  • 2 l r:给定?l,r,求?∑i=lr?ai??的值。

保证?1≤l≤r≤n,?∣x∣≤1e6。

输出格式

对于每个?2 l r?操作输出一行,每行有一个整数,表示所求的结果。

样例

InputOutput
3 2
1 2 3
1 2 0
2 1 3
6

数据范围与提示

对于所有数据,1≤n,q≤1e6,?∣ai?∣≤1e6,?1≤l≤r≤n,?∣x∣≤1e6。

前缀和思想

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n,q;
int a[1000010];
long long tree[1000010];
int lowbit(int x){
	return x & -x;
}
void add(int x,int v){
	while(x <= n){
		tree[x] += v;
		x += lowbit(x);
	}
}
long long get(int x){
	long long cnt = 0;
	while(x){
		cnt += tree[x];
		x -= lowbit(x);
	}
	return cnt;
}
void solve(){
	cin >> n >> q;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
		add(i,a[i]);
	}
	while(q--){
		int id,x,y;
		cin >> id >> x >> y;
		if(id == 1){
			add(x,y);
		}
		if(id == 2){
			cout << get(y) - get(x - 1) << endl;
		}
	}
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	solve();
	return 0;
}
/*

*/

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

题目描述

这是一道模板题。

给定数列?a[1],a[2],…,a[n],你需要依次进行?q?个操作,操作有两类:

  • 1 l r x:给定?l,r,x,对于所有?i∈[l,r],将?a[i]?加上?x(换言之,将?a[l],a[l+1],…,a[r]?分别加上?x);
  • 2 i:给定?i,求?a[i]?的值。

输入格式

第一行包含?2?个正整数?n,q,表示数列长度和询问个数。保证?1≤n,q≤1e6。
第二行?n?个整数?a[1],a[2],…,a[n],表示初始数列。保证?|a[i]|\le 10^6∣a[i]∣≤106。
接下来?q?行,每行一个操作,为以下两种之一:

  • 1 l r x:对于所有?i∈[l,r],将?a[i]?加上?x;
  • 2 i:给定?i,求?a[i]?的值。

保证?1≤l≤r≤n,?∣x∣≤1e6。

输出格式

对于每个?2 i?操作,输出一行,每行有一个整数,表示所求的结果。

样例

InputOutput
3 2
1 2 3
1 1 3 0
2 2
2

数据范围与提示

对于所有数据,1≤n,q≤1e6,?∣a[i]∣≤1e6,?1≤l≤r≤n,?∣x∣≤1e6。

差分+前缀和思想,STL库adjacent_difference动态数组求差分

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n,q;
int a[1000010],b[1000010];
long long tree[1000010];
int lowbit(int x){
	return x & -x;
}
void add(int x,int v){
	while(x <= n){
		tree[x] += v;
		x += lowbit(x);
	}
}
long long get(int x){
	long long cnt = 0;
	while(x){
		cnt += tree[x];
		x -= lowbit(x);
	}
	return cnt;
}
void solve(){
	cin >> n >> q;
	vector<int> c(n + 1);
	for(int i = 1;i <= n;i++){
		cin >> a[i];
	}
	adjacent_difference(a + 1,a + 1 + n,c.begin() + 1);
	for(int i = 1;i <= n;i++){
		tree[i] += c[i];
		long long j = i + lowbit(i);
		if(j <= n){
			tree[j] += tree[i];
		}
	}
	while(q--){
		int id,l,r,x;
		cin >> id;
		if(id == 1){
			cin >> l >> r >> x;
			add(l,x);
			add(r + 1,-x);
		}
		if(id == 2){
			cin >> l;
			cout << get(l) << endl;
		}
	}
	return ;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	solve();
	return 0;
}
/*

*/

树状数组 3 :区间修改,区间查询

题目描述

这是一道模板题。

给定数列 a[1],a[2],…,a[n],你需要依次进行?q?个操作,操作有两类:

  • 1 l r x:给定?l,r,x,对于所有?i∈[l,r],将?a[i]?加上?x(换言之,将?a[l],a[l+1],…,a[r]?分别加上?x);
  • 2 l r:给定?l,r,求?∑i=lr?a[i]?的值(换言之,求?a[l]+a[l+1]+?+a[r]?的值)。

输入格式

第一行包含?2?个正整数?n,q,表示数列长度和询问个数。保证?1≤n,q≤1e6。
第二行?n?个整数?a[1],a[2],…,a[n],表示初始数列。保证?∣a[i]∣≤1e6。
接下来?q?行,每行一个操作,为以下两种之一:

  • 1 l r x:对于所有?i∈[l,r],将?a[i]?加上?x;
  • 2 l r:输出?∑i=lr?a[i]?的值。

保证?1≤l≤r≤n,?∣x∣≤1e6。

输出格式

对于每个?2 l r?操作,输出一行,每行有一个整数,表示所求的结果。

样例

InputOutput
5 10
2 6 6 1 1
2 1 4
1 2 5 10
2 1 3
2 2 3
1 2 2 8
1 2 3 7
1 4 4 10
2 1 2
1 4 5 6
2 3 4
15
34
32
33
50

数据范围与提示

对于所有数据,1≤n,q≤1e6,?∣a[i]∣≤1e6,?1≤l≤r≤n,?∣x∣≤1e6。

差分+前缀和思想,adjacent_difference求差分,记得维护i*b[i]数组时加1ll*防止爆int

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
ll n, q;
ll a[1000010];
long long tree1[1000010],tree2[1000010];
ll lowbit(ll x) {
	return x & -x;
}
void add(ll p, ll x) {
	long long v = p * x;
	for (ll i = p; i <= n; i += lowbit(i)) {
		tree1[i] += x;
		tree2[i] += v;
	}
	return;
}
long long get(ll x) {
	long long ans = 0;
	for (ll i = x; i > 0; i -= lowbit(i)) {
		ans += (x + 1) * tree1[i] - tree2[i];
	}
	return ans;
}
void solve() {
	cin >> n >> q;
	for (ll i = 1; i <= n; i++) {
		cin >> a[i];
	}
	vector<long long> vec(n + 10);
	adjacent_difference(a + 1, a + 1 + n, vec.begin() + 1);
	for (ll i = 1; i <= n; i++) {
		tree1[i] += vec[i];
		tree2[i] += 1ll * vec[i] * i;
		long long j = i + lowbit(i);
		if (j <= n) {
			tree1[j] += tree1[i];
			tree2[j] += tree2[i];
		}
	}
	while (q--) {
		ll flag;
		cin >> flag;
		if (flag == 1) {
			ll l, r, x;
			cin >> l >> r >> x;
			add(l, x);
			add(r + 1, -x);
		}
		else {
			ll l, r;
			cin >> l >> r;
			cout << get(r) - get(l - 1) << endl;
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	solve();
	return 0;
}
/*

*/

二维树状数组:

二维树状数组 1:单点修改,区间查询

题目描述

这是一道模板题。

给出一个?n×m?的零矩阵?A,你需要完成如下操作:

  • 1 x y k:表示元素?Ax,y??自增?k;
  • 2 a b c d:表示询问左上角为?(a,b),右下角为?(c,d)?的子矩阵内所有数的和。

输入格式

输入的第一行有两个正整数?n,m;
接下来若干行,每行一个操作,直到文件结束。

输出格式

对于每个?2?操作,输出一个整数,表示对于这个操作的回答。

样例

InputOutput
2 2
1 1 1 3
1 2 2 4
2 1 1 2 2
7

数据范围与提示

对于?10%?的数据,n=1;
对于另?10%?的数据,m=1;
对于全部数据,1≤n,m≤2^12,1≤x,a,c≤n,1≤y,b,d≤m,∣k∣≤1e5,保证操作数目不超过?3×1e5,且询问的子矩阵存在。

差分思想

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n, m;
long long a[5000][5000];
int lowbit(int x) {
	return x & -x;
}
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)) {
			a[i][j] += k;
		}
	}
	return;
}
long long get(int x,int y) {
	long long sum = 0;
	for (int i = x; i > 0; i -= lowbit(i)) {
		for (int j = y; j > 0; j -= lowbit(j)) {
			sum += a[i][j];
		}
	}
	return sum;
}
void solve() {
	cin >> n >> m;
	int flag;
	memset(a, 0, sizeof(a));
	while (cin >> flag) {
		if (flag == 1) {
			int x, y, k;
			cin >> x >> y >> k;
			add(x, y, k);
		}
		else {
			int a, b, c, d;
			cin >> a >> b >> c >> d;
			cout << get(a - 1,b - 1) + get(c,d) - get(c,b-1)-get(a-1,d) << endl;
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	solve();
	return 0;
}
/*

*/

二维树状数组 2:区间修改,单点查询

题目描述

这是一道模板题。

给出一个?n×m?的零矩阵?A,你需要完成如下操作:

  • 1 a b c d k:表示左上角为?(a,b),右下角为?(c,d)?的子矩阵内所有数都自增?k;
  • 2 x y:表示询问元素?Ax,y??的值;

输入格式

输入的第一行有两个正整数?n,m;
接下来若干行,每行一个操作,直到文件结束。

输出格式

对于每个?2?操作,输出一个整数,表示对于这个操作的回答。

样例

InputOutput
2 2
1 1 1 2 2 5
1 1 2 2 2 -3
2 1 1
2 1 2
2 2 1
2 2 2
5
2
5
2

数据范围与提示

1≤n,m≤2^12,1≤x,a,c≤n,1≤y,b,d≤m,∣k∣≤1e5,保证操作数目不超过?3×1e5,且操作的子矩阵存在。

差分思想

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n, m;
long long a[5000][5000];
int lowbit(int x) {
	return x & -x;
}
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)) {
			a[i][j] += k;
		}
	}
	return;
}
long long get(int x, int y) {
	long long sum = 0;
	for (int i = x; i > 0; i -= lowbit(i)) {
		for (int j = y; j > 0; j -= lowbit(j)) {
			sum += a[i][j];
		}
	}
	return sum;
}
void solve() {
	cin >> n >> m;
	int flag;
	while (cin >> flag) {
		if (flag == 1) {
			int a, b, c, d, k;
			cin >> a >> b >> c >> d >> k;
			add(a, b, k);
			add(a, d + 1, -k);
			add(c + 1, b, -k);
			add(c + 1, d + 1, k);
		}
		else {
			int x, y;
			cin >> x >> y;
			cout << get(x, y) << endl;
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	solve();
	return 0;
}
/*

*/

二维树状数组 3:区间修改,区间查询

题目描述

这是一道模板题。

给定一个大小为?N×M?的零矩阵,直到输入文件结束,你需要进行若干个操作,操作有两类:

  • 1 a b c d x,表示将左上角为?(a,b),右下角为?(c,d)?的子矩阵全部加上?x;

  • 2 a b c d,表示询问左上角为?(a,b),右下角为?(c,d)?为顶点的子矩阵的所有数字之和。

输入格式

第一行两个正整数 ,其中?n,m?分别表示矩阵的行数与列数。

接下来若干行直到文件结束,均代表你需要进行的操作。

输出格式

对于每个?2?操作,输出一行代表查询的结果。

样例

InputOutput
4 4
1 1 1 3 3 2
1 2 2 4 4 1
2 2 2 3 3
12

数据范围与提示

对于10%?的数据,1≤n,m≤16,操作不超过?200?个;
对于60%?的数据,1≤n,m≤512;
对于?100%?的数据,1≤n,m≤2048,∣x∣≤500,操作不超过?2×1e5?个,保证运算过程中及最终结果均不超过?64?位带符号整数类型的表示范围,并且修改与查询的子矩阵存在。

差分思想

AC代码:

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <list>
#include <set>
#include <istream>
#include <sstream>
#include <iomanip>
#include <numeric>
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
using namespace std;
int n, m;
long long tree1[2050][2050], tree2[2050][2050], tree3[2050][2050], tree4[2050][2050];
int lowbit(int x) {
	return x & -x;
}
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)) {
			tree1[i][j] += k;
			tree2[i][j] += k * x;
			tree3[i][j] += k * y;
			tree4[i][j] += k * x * y;
		}
	}
	return;
}
long long get(int x, int y) {
	long long sum = 0;
	for (int i = x; i > 0; i -= lowbit(i)) {
		for (int j = y; j > 0; j -= lowbit(j)) {
			sum += (x + 1) * (y + 1) * tree1[i][j] - (x + 1) * tree3[i][j] - (y + 1) * tree2[i][j] + tree4[i][j];
		}
	}
	return sum;
}
void solve() {
	cin >> n >> m;
	int flag;
	while (cin >> flag) {
		if (flag == 1) {
			int a, b, c, d, x;
			cin >> a >> b >> c >> d >> x;
			add(a, b, x);
			add(a, d + 1, -x);
			add(c + 1, b, -x);
			add(c + 1, d + 1, x);
		}
		else {
			int a, b, c, d;
			cin >> a >> b >> c >> d;
			cout << get(a - 1, b - 1) + get(c, d) - get(c, b - 1) - get(a - 1, d) << endl;
		}
	}
	return;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	solve();
	return 0;
}
/*

*/

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-04 13:12:48  更:2021-12-04 13:14:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:42:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码