把旋转扔了, 点连续, 就是普通的线段树, 区间加和区间乘, 只不过是维护x,y,z三个序列
首先解决点不连续的问题, m很小, 明显是离散化
对于操作 [l, r], 转换为[L, R) //[l, r + 1)
把 L~R-1, 当坐一个点, 对于区间乘, 没影响
主要是区间加, 这时一个点内有 R - L 个点, 则区间加实则在这个点加了 (R - L) * add
就解决让点连续的问题
然后是旋转, 每3次一循环, 旋转标记 % 3
操作之间先旋转即可
即标记顺序为, 旋转, 区间乘, 区间加
const int N = 4e4 + 5, mod = 1e9 + 7;
struct query { ll op, l, r, x[3]; } a[N];
struct BIT {
struct node { int l, r, c; ll val[3], tag[5]; } tr[N * 40];
void push_up(int rt) { rep(i, 0, 2) tr[rt].val[i] = (tr[rt << 1].val[i] + tr[rt << 1 | 1].val[i]) % mod; }
void push_down(int rt) {
if (tr[rt].tag[4] == 1)
swap(tr[rt << 1].val[0], tr[rt << 1].val[1]), swap(tr[rt << 1].val[1], tr[rt << 1].val[2]),
swap(tr[rt << 1].tag[0], tr[rt << 1].tag[1]), swap(tr[rt << 1].tag[1], tr[rt << 1].tag[2]),
swap(tr[rt << 1 | 1].val[0], tr[rt << 1 | 1].val[1]), swap(tr[rt << 1 | 1].val[1], tr[rt << 1 | 1].val[2]),
swap(tr[rt << 1 | 1].tag[0], tr[rt << 1 | 1].tag[1]), swap(tr[rt << 1 | 1].tag[1], tr[rt << 1 | 1].tag[2]);
if (tr[rt].tag[4] == 2)
swap(tr[rt << 1].val[0], tr[rt << 1].val[2]), swap(tr[rt << 1].val[1], tr[rt << 1].val[2]),
swap(tr[rt << 1].tag[0], tr[rt << 1].tag[2]), swap(tr[rt << 1].tag[1], tr[rt << 1].tag[2]),
swap(tr[rt << 1 | 1].val[0], tr[rt << 1 | 1].val[2]), swap(tr[rt << 1 | 1].val[1], tr[rt << 1 | 1].val[2]),
swap(tr[rt << 1 | 1].tag[0], tr[rt << 1 | 1].tag[2]), swap(tr[rt << 1 | 1].tag[1], tr[rt << 1 | 1].tag[2]);
if (tr[rt].tag[3] ^ 1) rep(i, 0, 2)
tr[rt << 1].val[i] = tr[rt << 1].val[i] * tr[rt].tag[3] % mod,
tr[rt << 1].tag[i] = tr[rt << 1].tag[i] * tr[rt].tag[3] % mod,
tr[rt << 1 | 1].val[i] = tr[rt << 1 | 1].val[i] * tr[rt].tag[3] % mod,
tr[rt << 1 | 1].tag[i] = tr[rt << 1 | 1].tag[i] * tr[rt].tag[3] % mod;
rep(i, 0, 2) if (tr[rt].tag[i])
tr[rt << 1].val[i] = (tr[rt << 1].val[i] + tr[rt].tag[i] * tr[rt << 1].c % mod) % mod,
tr[rt << 1].tag[i] = (tr[rt << 1].tag[i] + tr[rt].tag[i]) % mod,
tr[rt << 1 | 1].val[i] = (tr[rt << 1 | 1].val[i] + tr[rt].tag[i] * tr[rt << 1 | 1].c % mod) % mod,
tr[rt << 1 | 1].tag[i] = (tr[rt << 1 | 1].tag[i] + tr[rt].tag[i]) % mod;
tr[rt << 1].tag[3] = tr[rt << 1].tag[3] * tr[rt].tag[3] % mod;
tr[rt << 1 | 1].tag[3] = tr[rt << 1 | 1].tag[3] * tr[rt].tag[3] % mod;
tr[rt << 1].tag[4] = (tr[rt << 1].tag[4] + tr[rt].tag[4]) % 3;
tr[rt << 1 | 1].tag[4] = (tr[rt << 1 | 1].tag[4] + tr[rt].tag[4]) % 3;
memset(tr[rt].tag, 0, sizeof tr[rt].tag); tr[rt].tag[3] = 1;
}
void build(int rt, int l, int r, vector<int>& c) {
tr[rt].l = l, tr[rt].r = r, tr[rt].c = c[r + 1] - c[l];
memset(tr[rt].val, 0, sizeof tr[rt].val);
memset(tr[rt].tag, 0, sizeof tr[rt].tag); tr[rt].tag[3] = 1;
if (l == r) return;
int mid = l + r >> 1;
build(rt << 1, l, mid, c); build(rt << 1 | 1, mid + 1, r, c);
}
void change(int rt, query& q) {
if (tr[rt].l >= q.l && tr[rt].r <= q.r) {
if (q.op == 1) rep(i, 0, 2)
tr[rt].val[i] = (tr[rt].val[i] + q.x[i] * tr[rt].c % mod) % mod, tr[rt].tag[i] = (tr[rt].tag[i] + q.x[i]) % mod;
else if (q.op == 2) {
rep(i, 0, 2) tr[rt].val[i] = tr[rt].val[i] * q.x[0] % mod, tr[rt].tag[i] = tr[rt].tag[i] * q.x[0] % mod;
tr[rt].tag[3] = tr[rt].tag[3] * q.x[0] % mod;
}
else {
swap(tr[rt].val[0], tr[rt].val[1]), swap(tr[rt].val[1], tr[rt].val[2]);
swap(tr[rt].tag[0], tr[rt].tag[1]), swap(tr[rt].tag[1], tr[rt].tag[2]);
tr[rt].tag[4] = (tr[rt].tag[4] + 1) % 3;
}
return;
}
push_down(rt); int mid = tr[rt].l + tr[rt].r >> 1;
if (mid >= q.l) change(rt << 1, q);
if (mid < q.r) change(rt << 1 | 1, q);
push_up(rt);
}
query ask(int rt, int l, int r) {
query ans, res;
if (tr[rt].l >= l && tr[rt].r <= r) return memcpy(ans.x, tr[rt].val, sizeof ans.x), ans;
push_down(rt); int mid = tr[rt].l + tr[rt].r >> 1;
if (mid >= l) ans = ask(rt << 1, l, r);
else memset(ans.x, 0, sizeof ans.x);
if (mid < r) { res = ask(rt << 1 | 1, l, r); rep(i, 0, 2) ans.x[i] = (ans.x[i] + res.x[i]) % mod; }
return ans;
}
} bit;
int n, m, _, k, cas;
vector<int> c;
int main() {
IOS; cin >> n >> m;
rep(i, 1, m) {
cin >> a[i].op >> a[i].l >> a[i].r; c.pb(a[i].l); c.pb(a[i].r + 1);
if (a[i].op == 1) cin >> a[i].x[0] >> a[i].x[1] >> a[i].x[2];
else if (a[i].op == 2) cin >> a[i].x[0];
}
sort(all(c)); c.erase(unique(all(c)), c.end());
bit.build(1, 0, c.size() - 1, c);
rep(i, 1, m) {
a[i].l = lower_bound(all(c), a[i].l) - c.begin(); a[i].r = upper_bound(all(c), a[i].r) - c.begin() - 1;
if (a[i].op ^ 4) bit.change(1, a[i]);
else {
a[i] = bit.ask(1, a[i].l, a[i].r); ll ans = 0;
rep(j, 0, 2) ans = (ans + sqr(a[i].x[j])) % mod;
cout << ans << '\n';
}
}
return 0;
}
用什么头文件
想问一下离散化为什么不能直接对l和r离散,把[l,r]变成[L, R]
这是区间修改, 加法要知道区间内实际有多少个点
离散化那里老哥能说明一下不
区间操作就 [L, R] 离散化操作区间端点, 合并区间为一个点
兄弟你没有填邀请码可以填一个,都可以得AC币!嘿嘿,谢谢兄弟
我的邀请码是:GUDFH