区间乘法可以标记永久化吗,求解答
查看原帖
区间乘法可以标记永久化吗,求解答
648953
1Stone楼主2022/10/7 20:37
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lch (R << 1)
#define rch ((R << 1) | 1)
#define mid ((l + r) >> 1)
ll val[100005], tree[400005], mul[400005], add[400005], N, T, mod;
void Build(ll R, ll l, ll r) {
	add[R] = 0; mul[R] = 1;
	if(l == r) {tree[R] = val[l]; return;}
	Build(lch, l, mid);
	Build(rch, mid + 1, r);
	tree[R] = (tree[lch] + tree[rch]) % mod;
}
ll Query(ll R, ll l, ll r, ll ql, ll qr, ll A, ll B) {
	if(l >= ql && r <= qr) return (tree[R] * A % mod + B * (r - l + 1) % mod) % mod;
	ll Sum = 0;
	if(mid >= ql) Sum = (Sum + Query(lch, l, mid, ql, qr, A * mul[R] % mod, (B * mul[R]+ add[R]) % mod)) % mod;
	if(mid + 1 <= qr) Sum = (Sum + Query(rch, mid + 1, r, ql, qr, A * mul[R] % mod, (B * mul[R] % mod + add[R]) % mod)) % mod;
	return Sum;
}
void Update(ll R, ll l, ll r, ll ql, ll qr, ll op, ll k) {
	ll len = (min(qr, r) - max(ql, l) + 1) % mod;
	if(op & 1) tree[R] = (tree[R] + Query(1, 1, N, max(ql, l), min(qr, r), 1, 0) * (len - 1) % mod) % mod;
	else (tree[R] += k * len % mod) %= mod;
	if(l >= ql && r <= qr) {
		if(op & 1) {
			(add[R] *= k) %= mod;
			(mul[R] *= k) %= mod;
		} 
		else (add[R] += k) %= mod;
		return;
	}
	if(mid >= ql) Update(lch, l, mid, ql, qr, op, k);
	if(mid + 1 <= qr) Update(rch, mid + 1, r, ql, qr, op, k);
}
int main()
{
	cin >> N >> T >> mod;
	for(int i = 1; i <= N; i++) cin >> val[i];
	Build(1, 1, N);
	while(T--) {
		ll op, x, y, k;
		cin >> op >> x >> y;
		if(op < 3) {
			cin >> k;
			Update(1, 1, N, x, y, op, k);	
		}
		else {
			cout << Query(1, 1, N, x, y, 1, 0) <<"\n";
		}
	}
	
	
	
	
	return 0;
}
2022/10/7 20:37
加载中...