社区讨论
求问主席树的标记永久化
学术版参与者 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 条回复,欢迎继续交流。
正在加载回复...