using namespace std;
#include <algorithm>
#include <array>
#include <bitset>
#include <climits>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <queue>
#include <stack>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <utility>
#include <map>
#include <vector>
#include <numeric>
#include <iostream>
#include <cstring>
using namespace std;
class ZKW_Differential {
private:
int n;
vector<int> tr;
public:
ZKW_Differential() =default;
ZKW_Differential(vector<int> & arr) {
n = 1;
while (n < (arr.size() + 2)) n <<= 1;
tr.resize(n << 1);
n++;
for (int i = 0; i < arr.size(); i++) {
tr[i + n] = arr[i];
}
for (int i = n - 2; i >= 1; i--) {
tr[i] = tr[i << 1] + tr[i << 1 | 1];
}
}
void update(int L, int R, int addValue, int subValue) {
for (tr[L += n] += addValue, L >>= 1; L; L >>= 1) {
tr[L] = tr[L << 1] + tr[L << 1 | 1];
}
for (tr[R += n + 1] -= subValue, R >>= 1; R; R >>= 1) {
tr[R] = tr[R << 1] + tr[R << 1 | 1];
}
}
int query(int L, int R) {
int res = 0;
for (L += n - 1, R += n + 1; L ^ R ^ 1; L >>= 1, R >>= 1) {
if (~L & 1) res += tr[L ^ 1];
if (R & 1) res += tr[R ^ 1];
}
return res;
}
};
class ZKW_SegmentTree {
public:
ZKW_Differential zkw_differential;
ZKW_Differential zkw_n_differential;
explicit ZKW_SegmentTree(vector<int> & arr) {
vector<int> tmp = arr;
adjacent_difference(arr.begin(), arr.end(), tmp.begin());
zkw_differential = ZKW_Differential(tmp);
for (int i = 0; i < arr.size(); i++) {
tmp[i] *= (i + 1);
}
zkw_n_differential = ZKW_Differential(tmp);
}
void update(int L, int R, int value) {
zkw_differential.update(L, R, value, value);
zkw_n_differential.update(L, R, (L + 1) *value, (R + 2) * value);
}
int query(int L) {
return ((L + 2) * zkw_differential.query(0, L) - zkw_n_differential.query(0, L));
}
int query(int L, int R) {
return query(R) - query(L - 1);
}
};
int main() {
vector<int> arr = {1, 2, 3, 4, 5};
ZKW_SegmentTree zkw_segment_tree(arr);
//cout << zkw_segment_tree.query(1, 3) << endl;
zkw_segment_tree.update(0, 4, 1);
for (int i = 0; i < 5; i++) {
for (int j = i; j <5; j++) {
cout << i << "\t" << j << ": " << zkw_segment_tree.query(i, j) << endl;
}
}
}
c++ 支持区间修改的区间和线段树
于 2024-06-16 01:53:04 首次发布