像vector<typename> 一样定义自己的结构体
  • 板块学术版
  • 楼主caoshuchen
  • 当前回复18
  • 已保存回复18
  • 发布时间2024/7/15 16:58
  • 上次更新2024/7/18 15:34:16
查看原帖
像vector<typename> 一样定义自己的结构体
676351
caoshuchen楼主2024/7/15 16:58

前言

大家应该经常发现,在做多数据结构杂糅的题目时,可能会出现许多冲突,如:

多个结构都需要 ValueValue 这一类型的变量,但是不同的数据结构需要不同的 ValueValue 实现不同的功能,这样一来我们就需要定义多个 ValueValue 结构体,且名字不能重复,这也会使我们的模板需要稍微调整。

或者说需要两个线段树,但他们实现的功能不同,这样一来就要写两大坨模板,但却几乎完全相同,不同的仅仅是存储的 valuevalue 和 tagtag 的类型

有办法让我们不这么做吗?

像 vector<>vector<> 一样定义结构体

我们发现像 vector<type>vector<type> 和 map<type1,type2>map<type1,type2> 这样的数据结构可以存储任意类型的数据,非常方便。我们自己可以这么做吗?

template <typename t1, typename t2>
struct segTree {
    t1 val;
    t2 tag;
};

segTree<Value, Tag> st;

如上,我们就这样定义了这样一个数据结构,我们将他运用到线段树模板上:

P1471方差P1471 方差

以这题为例:

//请不要把我的代码直接贴上去提交!

#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;
}
2024/7/15 16:58
加载中...