自学内容网 自学内容网

树状数组专题

树状数组相较于线段树好写,但是局限于查询区间和,没啥功能

落谷3374

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
int b[1000];
const int N = 500005;
int n, m;

inline int lowbit(int x) {
return x & (-x);
}

ll count(int p) {
if (p == 0) return 0;
return count(p - lowbit(p)) + b[p];
}

void add(int p,int x) {
while (p <=n) {
b[p] += x;
p += lowbit(p);
}
}

int main() {
cin >> n >> m;
int a;
for (int i = 1; i <= n; i++) {
cin >> a;
add(i, a);
}
int x, y;
while (m--) {
cin >> a >> x >> y;
if (a == 1) {
add(x, y);
}
else {
cout << count(y) - count(x - 1) << endl;
}
}
return 0;
}

落谷 3368

在这里插入图片描述

这个题目不同于上面这个题,我们需要,数组中装的不再是和,而是差分

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 500005;
int a[N];
int n, m;

inline int lowbit(int x) {
return x & (-x);
}

void add(int x, int p) {
while (x <= n) {
a[x] += p;
x += lowbit(x);
}
}

ll count(int x) {
if (x == 0) return 0;
return count(x - lowbit(x)) + a[x];
}

int main() {
cin >> n >> m;
int b;
int last = 0;
for (int i = 1; i <= n; i++) {
cin >> b;
add(i, b-last);    // 构造一个前缀差分
last = b;
}
int c, d, e;
while (m--) {
cin >> b;
if (b == 1) {
cin >> c >> d >> e;
add(c, e);
add(d + 1, -e);
}
else {
cin >> c;
cout << count(c) << endl;
}
}
return 0;
}

luogu5057

在这里插入图片描述

如果这个用普通的前缀和的话,会tle两个点

这个题目的关键就是

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;

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

inline int lowbit(int x) {
return x & (-x);
}

void add(int x, int p) {
while (x <= n) {
a[x] += p;
x += lowbit(x);
}
}

int count(int x) {
if (x == 0) return 0;
return count(x - lowbit(x)) + a[x];
}

int main() {
cin >> n >> m;
int t, b, c;
while (m--) {
cin >> t;
if (t == 1) {
cin >> b >> c;
add(b, 1);
add(c+1, 1);
}
else {
cin >> b;
int ans = 0;
cout << count(b) % 2 << endl;
}
}
return 0;
}

原文地址:https://blog.csdn.net/wniuniu_/article/details/139105249

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!