大家应该经常发现,在做多数据结构杂糅的题目时,可能会出现许多冲突,如:
多个结构都需要 Value 这一类型的变量,但是不同的数据结构需要不同的 Value 实现不同的功能,这样一来我们就需要定义多个 Value 结构体,且名字不能重复,这也会使我们的模板需要稍微调整。
或者说需要两个线段树,但他们实现的功能不同,这样一来就要写两大坨模板,但却几乎完全相同,不同的仅仅是存储的 value 和 tag 的类型
有办法让我们不这么做吗?
我们发现像 vector<type> 和 map<type1,type2> 这样的数据结构可以存储任意类型的数据,非常方便。我们自己可以这么做吗?
template <typename t1, typename t2>
struct segTree {
t1 val;
t2 tag;
};
segTree<Value, Tag> st;
如上,我们就这样定义了这样一个数据结构,我们将他运用到线段树模板上:
以这题为例:
//请不要把我的代码直接贴上去提交!
#include <bits/stdc++.h>
using namespace std;
typedef long double ll;
const ll inf = 0x3f3f3f3f3f3f3f3f;
struct SegValue {
ll sum, sqs, len;
SegValue() {
len = 0;
sum = sqs = 0;
}
SegValue(ll x) {
sum = x;
sqs = x * x;
len = 1;
}
};
struct SegTag {
ll a;
SegTag() {
a = 0;
}
SegTag(ll A) {
a = A;
}
};
SegValue operator+(SegValue x, SegValue y) {
SegValue ans;
ans.sum = x.sum + y.sum;
ans.sqs = x.sqs + y.sqs;
ans.len = x.len + y.len;
return ans;
}
SegTag operator*(SegTag x, SegTag y) {
return SegTag(x.a + y.a);
}
SegValue operator*(SegValue x, SegTag y) {
x.sqs += 2 * y.a * x.sum + x.len * y.a * y.a;
x.sum += x.len * y.a;
return x;
}
template<typename Value, typename Tag>
struct SegTree {
int sz = 0;
vector<Value> val;
vector<Tag> tag;
Value ide1 = Value();
Tag ide2 = Tag();
void pushdown(int x, int lx, int rx) {
val[x * 2] = val[x * 2] * tag[x];
val[x * 2 + 1] = val[x * 2 + 1] * tag[x];
tag[x * 2] = tag[x * 2] * tag[x];
tag[x * 2 + 1] = tag[x * 2 + 1] * tag[x];
tag[x] = ide2;
}
void pushup(int x, int lx, int rx) {
pushdown(x, lx, rx);
val[x] = val[x * 2] + val[x * 2 + 1];
}
void build(int x, int lx, int rx, vector<Value> &a) {
if (lx + 1 == rx) {
val[x] = (lx <= a.size() ? a[lx - 1] : ide1);
return ;
}
int mid = (lx + rx) / 2;
build(x * 2, lx, mid, a), build(x * 2 + 1, mid, rx, a);
pushup(x, lx, rx);
}
Value qry(int x, int lx, int rx, int l, int r) {
if (l <= lx && rx <= r)
return val[x];
if (rx <= l || lx >= r)
return ide1;
int mid = (lx + rx) / 2;
pushdown(x, lx, rx);
return qry(x * 2, lx, mid, l, r) + qry(x * 2 + 1, mid, rx, l, r);
}
void mdf(int x, int lx, int rx, int l, int r, Tag t) {
if (l <= lx && rx <= r) {
val[x] = val[x] * t;
tag[x] = tag[x] * t;
return ;
}
if (rx <= l || lx >= r)
return ;
int mid = (lx + rx) / 2;
pushdown(x, lx, rx);
mdf(x * 2, lx, mid, l, r, t), mdf(x * 2 + 1, mid, rx, l, r, t);
pushup(x, lx, rx);
}
SegTree(vector<Value> &a) {
for (sz = 1; sz < a.size(); sz *= 2);
val.assign(sz * 2, ide1);
tag.assign(sz * 2, ide2);
build(1, 1, sz + 1, a);
}
SegTree(){}
};
SegTree<SegValue, SegTag> st;
vector<SegValue> a;
int n, m;
int main() {
cin >> n >> m;
for (ll i = 1, x; i <= n; i++)
(cin >> x), a.push_back(SegValue(x));
st = SegTree<SegValue, SegTag>(a);
for (ll i = 1, op, l, r, v, x, j; i <= m; i++) {
cin >> op;
if (op == 1) {
cin >> l >> r >> v;
st.mdf(1, 1, st.sz + 1, l, r + 1, SegTag(v));
}
else {
cin >> l >> r;
ll len = r - l + 1;
if (op == 2)
printf("%.4Lf\n", 1.0 * st.qry(1, 1, st.sz + 1, l, r + 1).sum / len);
else {
SegValue tmp = st.qry(1, 1, st.sz + 1, l, r + 1);
double ba = 1.0 * tmp.sum / len;
printf("%.4Lf\n", (tmp.sqs - 2 * ba * tmp.sum + ba * ba * (r - l + 1)) / len);
}
}
}
return 0;
}