如题,给出一种数据结构的模板
#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
class SegmentTree {
private:
int fp;
struct Tnode {
int LeftChild,RightChild;
int l,r;
int Max,Min;
int delta;
long long sum;
Tnode() {
LeftChild = RightChild = l = r = Max = Min = delta = 0;
sum = 0ll;
}
}tree[100010];
void pushdown(int root) {
if(tree[root].delta == 0) return;
Tnode &lc = tree[ tree[root].LeftChild ],&rc = tree[ tree[root].RightChild ];
int lenlc = getlen(tree[root].LeftChild),lenrc = getlen(tree[root].RightChild);
lc.delta += tree[root].delta;
rc.delta += tree[root].delta;
lc.Max += tree[root].delta;
rc.Max += tree[root].delta;
lc.Min += tree[root].delta;
rc.Min += tree[root].delta;
lc.sum += tree[root].delta * lenlc;
rc.sum += tree[root].delta * lenrc;
tree[root].delta = 0;
}
void pushup(int root) {
Tnode &lc = tree[ tree[root].LeftChild ],&rc = tree[ tree[root].RightChild ];
tree[root].sum = lc.sum + rc.sum;
tree[root].Max = max(lc.Max,rc.Max);
tree[root].Min = min(lc.Min,rc.Min);
}
int getpoint(int l,int r) {
++fp;
tree[fp].l = l;
tree[fp].r = r;
return fp;
}
int getlen(int root) {
return tree[root].r - tree[root].l + 1;
}
public:
SegmentTree() {
fp = 0;
}
int create(int l,int r) {
int root = getpoint(l,r);
if(l == r) {
return root;
}
tree[root].LeftChild = create(l,l + r >> 1);
tree[root].RightChild = create((l + r >> 1) + 1,r);
return root;
}
long long query_sum(int root,int l,int r) {
if(tree[root].r < l || r < tree[root].l) {
return 0ll;
}
if(l <= tree[root].l && tree[root].r <= r) {
return tree[root].sum;
}
long long result = 0;
result += query_sum(tree[root].LeftChild,l,r);
result += query_sum(tree[root].RightChild,l,r);
return result;
}
void update(int root,int l,int r,int delta) {
if(tree[root].r < l || r < tree[root].l) {
return;
}
if(l <= tree[root].l && tree[root].r <= r) {
tree[root].delta += delta;
tree[root].Max += delta;
tree[root].Min += delta;
tree[root].sum += getlen(root) * delta;
return;
}
pushdown(root);
update(tree[root].LeftChild,l,r,delta);
update(tree[root].RightChild,l,r,delta);
pushup(root);
}
int query_max(int root,int l,int r) {
if(tree[root].r < l || r < tree[root].l) {
return 0;
}
if(l <= tree[root].l && tree[root].r <= r) {
return tree[root].Max;
}
int result = 0;
result = max(result,query_max(tree[root].LeftChild,l,r));
result = max(result,query_max(tree[root].RightChild,l,r));
return result;
}
int query_min(int root,int l,int r) {
if(tree[root].r < l || r < tree[root].l) {
return 0;
}
if(l <= tree[root].l && tree[root].r <= r) {
return tree[root].Min;
}
int result = 0;
result = min(result,query_min(tree[root].LeftChild,l,r));
result = min(result,query_min(tree[root].RightChild,l,r));
return result;
}
};
SegmentTree st;
int main() {
int n;
cin >> n;
int root = st.create(1,n);
int m;
cin >> m;
for(int i = 0;i < m;i++) {
string oper;
cin >> oper;
int l,r;
cin >> l >> r;
if(oper == "Add") {
int delta;
cin >> delta;
st.update(root,l,r,delta);
}
if(oper == "Sum") {
cout << st.query_sum(root,l,r) << endl;
}
if(oper == "Max") {
cout << st.query_max(root,l,r) << endl;
}
if(oper == "Min") {
cout << st.query_min(root,l,r) << endl;
}
}
return 0;
}
支持求和,求最大值,最小值,区间修改的操作
简单描述:
将线段树写成一个类,设置会访问到的函数为公开,比如说查询,修改的操作
将不会使用到,但在类中互相调用的设置为私有
简单描述原理:
一开始建树,把这一棵树的每一个节点都给予一个保存的线段的左右端点
通过lazy-tag的方式,保存每一次需要增加的值,如果这一个节点中所有的子节点都会被这个操作影响,就把标记放置在当前位置
如果需要修改它的子节点,就会把标记下传
在求区间的值的时候,判断是否包含或者相交,分解问题,求出每一个子问题,最后得到答案