一、单点修改、区间查询
例: 已知一个数列,有两种操作:
1、将某一个数加上x
2、求出某区间每一个数的和
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 10;
int tr[N], a[N];
int n, tt;
int lowbit(int x) {
return x & -x;
}
void add(int x, int c) {
for(int i = x; i <= n; i += lowbit(i)) {
tr[i] += c;
}
}
LL sum(int x) {
LL res = 0;
for(int i = x; i > 0; i -= lowbit(i)) {
res += tr[i];
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> tt;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
add(i, a[i]);
}
while(tt --) {
int op;
cin >> op;
if(op == 1) {
int x, k;
cin >> x >> k;
add(x, k);
} else {
int l, r;
cin >> l >> r;
cout << sum(r) - sum(l - 1) << '\n';
}
}
return 0;
}
二、区间修改、单点查询
例: 已知一个数列,有两种操作:
1、将某区间每一个数加上x
2、求出某一个数的值
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 10;
int tr[N], a[N];
int n, tt;
int lowbit(int x) {
return x & -x;
}
void add(int x, int c) {
for(int i = x; i <= n; i += lowbit(i)) {
tr[i] += c;
}
}
LL sum(int x) {
LL res = 0;
for(int i = x; i > 0; i -= lowbit(i)) {
res += tr[i];
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> tt;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
add(i, a[i] - a[i - 1]);
}
while(tt --) {
int op;
cin >> op;
if(op == 1) {
int l, r, x;
cin >> l >> r >> x;
add(l, x);
add(r + 1, -x);
} else {
int x;
cin >> x;
cout << sum(x) << '\n';
}
}
return 0;
}
三、区间修改、区间查询(需要额外的辅助数组)
例: 已知一个数列,有两种操作:
1、将某区间每一个数加上x
2、求出某区间每一个数的和
计算推导
b
1
_1
1 = a
1
_1
1
b
2
_2
2 = a
2
_2
2 - a
1
_1
1
…
b
n
_n
n = a
n
_n
n - a
n
−
1
_{n-1}
n−1
数组a的前缀和: S = a 1 _1 1 + a 2 _2 2 + … + a n _n n
a
0
_0
0 = 0
a
1
_1
1 = b
1
_1
1
a
2
_2
2 = b
1
_1
1 + b
2
_2
2
a
3
_3
3 = b
1
_1
1 + b
2
_2
2 + b
3
_3
3
…
a
n
_n
n = b
1
_1
1 + b
2
_2
2 + b
3
_3
3 + … + b
n
_n
n
S =
∑
1
n
\sum_1^n
∑1na
i
_i
i = (n + 1) * (b
1
_1
1 + b
2
_2
2 + … + b
n
_n
n) - (1 * b
1
_1
1 + 2 * b
2
_2
2 + … + n * b
n
_n
n)
即S = (n + 1) *
∑
1
n
\sum_1^n
∑1nb
i
_i
i -
∑
1
n
\sum_1^n
∑1ni * b
i
_i
i
可用 tr1 维护 b
i
_i
i 的前缀和,tr2维护 i * b
i
_i
i 的前缀和
则在代码中S可表示为(x + 1) * sum(tr1, x) - sum(tr2, x)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
LL a[N], tr1[N], tr2[N];
int n, tt;
int lowbit(int x) {
return x & -x;
}
void add(LL tr[], int x, LL c) {
for(int i = x; i <= n; i += lowbit(i)) {
tr[i] += c;
}
}
LL sum(LL tr[], int x) {
LL res = 0;
for(int i = x; i > 0; i -= lowbit(i)) {
res += tr[i];
}
return res;
}
LL presum(LL x) {
return (x + 1) * sum(tr1, x) - sum(tr2, x);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> tt;
for(int i = 1; i <= n; i ++) {
cin >> a[i];
LL u = a[i] - a[i - 1];
add(tr1, i, u);
add(tr2, i, (LL) i * u);
}
while(tt --) {
int op;
cin >> op;
if(op == 2) {
int l, r;
cin >> l >> r;
cout << presum(r) - presum(l - 1) << '\n';
} else {
int l, r, c;
cin >> l >> r >> c;
add(tr1, l, c);
add(tr1, r + 1, -c);
add(tr2, l, l * c);
add(tr2, r + 1, (r + 1) * -c);
}
}
return 0;
}

被折叠的 条评论
为什么被折叠?



