社区讨论

求问主席树的标记永久化

学术版参与者 5已保存回复 9

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
8 条
当前快照
1 份
快照标识符
@miu0kc8y
此快照首次捕获于
2025/12/06 16:10
2 个月前
此快照最后确认于
2025/12/08 18:20
2 个月前
查看原帖
我想写一个区间加区间乘区间求和的主席树,求问以下写法是否正确(不考虑区间乘里query的时间复杂度问题,只要正确性即可),蒟蒻已经写挂了n遍了……
CPP
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
const int mod = 1e9 + 7;
struct Tree
{
	int l, r, a, lazy1, lazy2, ls, rs;
	Tree()
	{
		l = r = a = lazy1 = ls = rs = 0;
		lazy2 = 1;
	}
	Tree operator+(const Tree &b) const
	{
		Tree ret;
		ret.a = (0ll + a + b.a) % mod;
		return ret;
	}
	void tag1(int c)
	{
		lazy1 = 1ll * lazy1 * c % mod;
	}
	void tag2(int c)
	{
		lazy1 = 1ll * lazy1 * c % mod;
		lazy2 = 1ll * lazy2 * c % mod;
	}
}
tree[2][5200005];
long long n[2], m, a[2][50005], rt[2][100005], rti, nowrt[2], l, r, c;
string opt;
void pushup(Tree tree[], int rt)
{
	tree[rt].a = (tree[tree[rt].ls] + tree[tree[rt].rs]).a;
}
int mkt(Tree tree[], bool b, int l, int r)
{
	int rt = ++rti;
	tree[rt].l = l;
	tree[rt].r = r;
	if (l >= r)
	{
		tree[rt].a = a[b][l];
		return rt;
	}
	int mid = (l + r) >> 1;
	tree[rt].ls = mkt(tree, b, l, mid);
	tree[rt].rs = mkt(tree, b, mid + 1, r);
	pushup(tree, rt);
	return rt;
}
int query(Tree tree[], int L, int R, int lazy1, int lazy2, int l, int r, int rt)
{
	if (L > R)
	{
		return 0;
	}
	if (L <= l && r <= R)
	{
		return 1ll * (tree[rt].a + (r - l + 1ll) * lazy1 % mod) % mod * lazy2 % mod;
	}
	int mid = (l + r) >> 1, ret = 0;
	if (L <= mid)
	{
		ret = (0ll + ret + query(tree, L, R, (0ll + lazy1 + tree[rt].lazy1) % mod, 1ll * lazy2 * tree[rt].lazy2 % mod, l, mid, tree[rt].ls)) % mod;
	}
	if (mid < R)
	{
		ret = (0ll + ret + query(tree, L, R, (0ll + lazy1 + tree[rt].lazy1) % mod, 1ll * lazy2 * tree[rt].lazy2 % mod, mid + 1, r, tree[rt].rs)) % mod;
	}
	return ret;
}
int update1(Tree tree[], int L, int R, int c, int l, int r, int prt)
{
	int nrt = ++rti;
	tree[nrt] = tree[prt];
	tree[nrt].a = (0ll + tree[nrt].a + (min(R, r) - max(L, l) + 1ll) * c % mod) % mod;
	if (L > R)
	{
		return nrt;
	}
	if (L <= l && r <= R)
	{
		tree[nrt].tag1(c);
		return nrt;
	}
	int mid = (l + r) >> 1;
	if (L <= mid)
	{
		tree[nrt].ls = update1(tree, L, R, c, l, mid, tree[nrt].ls);
	}
	if (mid < R)
	{
		tree[nrt].rs = update1(tree, L, R, c, mid + 1, r, tree[nrt].rs);
	}
	return nrt;
}
int update2(Tree tree[], bool b, int L, int R, int c, int l, int r, int prt)
{
	if (L > R)
	{
		return 0;
	}
	int nrt = ++rti;
	tree[nrt] = tree[prt];
	tree[nrt].a = (0ll + tree[nrt].a + 1ll * query(tree, max(L, l), min(R, r), 0, 1, 1, n[b], nowrt[b]) * c % mod) % mod;
	if (L <= l && r <= R)
	{
		tree[nrt].tag2(c);
		return nrt;
	}
	int mid = (l + r) >> 1;
	if (L <= mid)
	{
		tree[nrt].ls = update2(tree, b, L, R, c, l, mid, tree[nrt].ls);
	}
	if (mid < R)
	{
		tree[nrt].rs = update2(tree, b, L, R, c, mid + 1, r, tree[nrt].rs);
	}
	return nrt;
}
int main()
{
	cin.tie(0)->ios::sync_with_stdio(false);
	cout.tie(0);
	cin >> n[1] >> m;
	n[0] = n[1] / 2;
	n[1] = (n[1] + 1) / 2;
	for (int i = 1;i <= n[0] + n[1];i++)
	{
		cin >> a[i % 2][(i + 1) / 2];
	}
	rt[0][nowrt[0] = 0] = mkt(tree[0], 0, 1, n[0]);
	rt[1][nowrt[1] = 0] = mkt(tree[1], 1, 1, n[1]);
	while (m--)
	{
		cin >> opt;
		if (opt == "0")
		{
			cin >> c;
			nowrt[0]++;
			rt[0][nowrt[0]] = rt[0][nowrt[0] - c - 1];
			nowrt[1]++;
			rt[1][nowrt[1]] = rt[1][nowrt[1] - c - 1];
		}
		else if (opt == "1")
		{
			cin >> l >> r >> c;
			int l0 = (l + 1) / 2, r0 = r / 2, l1 = l / 2 + 1, r1 = (r + 1) / 2;
			nowrt[0]++;
			rt[0][nowrt[0]] = update1(tree[0], l0, r0, c, 1, n[0], rt[0][nowrt[0] - 1]);
			nowrt[1]++;
			rt[1][nowrt[1]] = update1(tree[1], l1, r1, c, 1, n[1], rt[1][nowrt[1] - 1]);
		}
		else if (opt == "1.5")
		{
			cin >> l >> r >> c;
			int l0 = (l + 1) / 2, r0 = r / 2, l1 = l / 2 + 1, r1 = (r + 1) / 2;
			if (l % 2)
			{
				nowrt[0]++;
				rt[0][nowrt[0]] = update1(tree[0], l0, r0, c, 1, n[0], rt[0][nowrt[0] - 1]);
				nowrt[1]++;
				rt[1][nowrt[1]] = update1(tree[1], l1, r1, mod - c, 1, n[1], rt[1][nowrt[1] - 1]);
			}
			else
			{
				nowrt[0]++;
				rt[0][nowrt[0]] = update1(tree[0], l0, r0, mod - c, 1, n[0], rt[0][nowrt[0] - 1]);
				nowrt[1]++;
				rt[1][nowrt[1]] = update1(tree[1], l1, r1, c, 1, n[1], rt[1][nowrt[1] - 1]);
			}
		}
		else if (opt == "2")
		{
			cin >> l >> r >> c;
			int l0 = (l + 1) / 2, r0 = r / 2, l1 = l / 2 + 1, r1 = (r + 1) / 2;
			nowrt[0]++;
			rt[0][nowrt[0]] = update2(tree[0], 0, l0, r0, c, 1, n[0], rt[0][nowrt[0] - 1]);
			nowrt[1]++;
			rt[1][nowrt[1]] = update2(tree[1], 1, l1, r1, c, 1, n[1], rt[1][nowrt[1] - 1]);
		}
		else
		{
			cin >> l >> r;
			int l0 = (l + 1) / 2, r0 = r / 2, l1 = l / 2 + 1, r1 = (r + 1) / 2;
			cout << (0ll + query(tree[0], l0, r0, 0, 1, 1, n[0], rt[0][nowrt[0]]) + query(tree[1], l1, r1, 0, 1, 1, n[1], rt[1][nowrt[1]])) % mod << "\n";
		}
	}
	return 0;
}

回复

9 条回复,欢迎继续交流。

正在加载回复...