【单点修改,区间查询】洛谷 P3374 【模板】树状数组 1
题目
https://www.luogu.com.cn/problem/P3374
参考代码
#include<bits/stdc++.h>
typedef long long ll;
template<typename E, typename F, typename F_INVERSE>
class FenwickTree {// 树状数组
private:
std::vector<E> raw;// 维护原数据
std::vector<E> tree;// 树状数组
int arr_size;// 元素个数
F func;// 代表元素运算规则,例如加法
F_INVERSE func_inverse;// 代表 func 的逆运算规则,例如加法的逆运算规则就是减法
E defaultValue;// 树状数组初始化的元素值
bool prefixToSuffix;// 用前缀树状数组维护后缀树状数组
/* 计算出 x 二进制形式下最低位的 1 */
inline int lowbit(int x) {
return x & -x;
}
/* 有可能使用前缀树状数组维护后缀树状数组,因此需要计算出真实下标位置 */
inline int calculateRealIndex(int x) {
return prefixToSuffix ? arr_size - x + 1 : x;
}
public:
/**
* 容器内的元素下标从 0 开始存放,但是树状数组的使用是从下标 1 开始使用
* @tparam Container 容器类型
* @param arr 存放元素的容器
* @param arr_size 容器大小
* @param func 容器中元素的运算规则
* @param func_inverse 容器中元素的逆运算规则
* @param defaultValue 容器中元素的默认值
*/
template<typename Container>
FenwickTree(Container&& arr, int arr_size, F func, F_INVERSE func_inverse, E defaultValue, bool prefixToSuffix = false)
: arr_size(arr_size), func(func), func_inverse(func_inverse), defaultValue(defaultValue), prefixToSuffix(prefixToSuffix) {
raw.resize(arr_size + 1);
tree.assign(arr_size + 1, defaultValue);
for (int i = 0; i < arr_size; ++ i) {
raw[i + 1] = arr[i];
pointUpdate(i + 1, arr[i]);
}
}
/* 没有初始容器数据的构造器 */
FenwickTree(int arr_size, F func, F_INVERSE func_inverse, E defaultValue, bool prefixToSuffix = false)
: arr_size(arr_size), func(func), func_inverse(func_inverse), defaultValue(defaultValue), prefixToSuffix(prefixToSuffix) {
raw.assign(arr_size + 1, defaultValue);
tree.assign(arr_size + 1, defaultValue);
}
/* 单点赋值:将下标 index(从 1 开始)的值改为 newValue */
void pointAssign(int index, E newValue) {
// 原本的值为 value 要变为 newValue,相当于 func(value, func_inverse(newValue, value))
index = calculateRealIndex(index);
E delta = func_inverse(newValue, raw[index]);
raw[index] = newValue;
pointUpdate(index, delta);
}
/* 单点修改:将下标 index(从 1 开始)的值与 value 进行 func 运算 */
void pointUpdate(int index, E value) {
index = calculateRealIndex(index);
for (int i = index; i <= arr_size; i += lowbit(i)) {
tree[i] = func(tree[i], value);
}
}
/* 前缀查询:查询下标 index(从 1 开始)的值 */
E prefixQuery(int index) {
index = calculateRealIndex(index);
E res = defaultValue;
for (int i = index; i > 0; i -= lowbit(i)) {
res = func(res, tree[i]);
}
return res;
}
/* 区间查询:查询区间 [leftIndex, rightIndex] 进行 func 运算的结果 */
E rangeQuery(int leftIndex, int rightIndex) {
E difference = func_inverse(prefixQuery(rightIndex), prefixQuery(leftIndex - 1));// 使用 func 的逆运算规则 func_inverse 做差分
return difference;// 差分的值即为区间 [leftIndex, rightIndex] 进行 func 运算的结果
}
};
class FenwickTreeFactory {
public:
/* 前缀模式的加法树状数组:修改向后,查询向前 */
template<typename Container>
static auto add(Container&& arr, int arrSize, bool prefixToSuffix = false) {
using T = std::remove_reference_t<decltype(arr[0])>;
auto add_func = [](T a, T b) { return a + b; };
auto sub_func = [](T a, T b) { return a - b; };
return FenwickTree<T, decltype(add_func), decltype(sub_func)>(
std::forward<Container>(arr), arrSize, add_func, sub_func, T(0), prefixToSuffix);
}
/* 后缀模式的加法树状数组:修改向前,查询向后 */
template<typename Container>
static auto addSuffix(Container&& arr, int arrSize) {
return add(arr, arrSize, true);
}
// 乘法树状数组
template<typename Container>
static auto mul(Container&& arr, int arrSize) {
using T = std::decay_t<decltype(arr[0])>;
return FenwickTree<T,
decltype([](T a, T b) { return a * b; }),
decltype([](T a, T b) { return a / b; })
>(std::forward<Container>(arr), arrSize,
[](T a, T b) { return a * b; },
[](T a, T b) { return a / b; },
T(1));
}
// 异或树状数组
template<typename Container>
static auto xors(Container&& arr, int arrSize) {
using T = std::decay_t<decltype(arr[0])>;
auto op = [](T a, T b) { return a ^ b; };
return FenwickTree<T, decltype(op), decltype(op)>(
std::forward<Container>(arr), arrSize, op, op, T(0));
}
// 模加法树状数组
template<typename Container>
static auto modAdd(Container&& arr, int arrSize,
std::decay_t<decltype(arr[0])> mod) {
using T = std::decay_t<decltype(arr[0])>;
auto add = [mod](T a, T b) { return (a + b) % mod; };
auto sub = [mod](T a, T b) { return (a - b + mod) % mod; };
return FenwickTree<T, decltype(add), decltype(sub)>(
std::forward<Container>(arr), arrSize, add, sub, T(0));
}
// 通用自定义工厂
template<typename Container, typename Func, typename InvFunc>
static auto custom(Container&& arr, int arrSize,
Func func, InvFunc invFunc,
std::decay_t<decltype(arr[0])> defaultVal) {
using T = std::decay_t<decltype(arr[0])>;
return FenwickTree<T, Func, InvFunc>(
std::forward<Container>(arr), arrSize, func, invFunc, defaultVal);
}
};
constexpr int N = 5e5 + 7;
int a[N];
int main() {
std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);
#ifdef ACM_LOCAL
freopen("testCase.in", "r", stdin);
freopen("testCase.out", "w", stdout);
#endif
int n, m, op, x, y;
std::cin >> n >> m;
for (int i = 0; i < n; ++i) std::cin >> a[i];
auto tr = FenwickTreeFactory::add(a, n);
while (m --) {
std::cin >> op >> x >> y;
if (op == 1) {
tr.pointUpdate(x, y);
} else {
std::cout << tr.rangeQuery(x, y) << '\n';
}
}
return 0;
}
浙公网安备 33010602011771号