爆0求调
查看原帖
爆0求调
365433
Mark_M楼主2023/1/16 11:08
#include <iostream>
#define ll long long
using namespace std;
const ll N = 10005;
ll n, m, mod;
ll num[N];
ll sum[N * 4];
ll tag1[N * 4];//multiply
ll tag2[N * 4];//plus

ll lc(ll p) {
	return p << 1;
}

ll rc(ll p) {
	return p << 1 | 1;
}

void PushUp(ll p) {
	sum[p] = ((sum[lc(p)] % mod) + (sum[rc(p)] % mod)) % mod;
}

void Build(ll p, ll l, ll r) {
	tag1[p] = 1;
	tag2[p] = 0;
	if (l == r) {
		sum[p] += (num[l] % mod);
		return;
	}
	ll mid = (l + r) >> 1;
	Build(lc(p), l, mid);
	Build(rc(p), mid + 1, r);
	PushUp(p);
}
void moveTag_Mu(ll p, ll l, ll r, ll t) {
	sum[p] += ((t % mod) * ((r - l + 1) % mod)) % mod;
	tag2[p] *= (tag2[p] % mod) * (t % mod);
}

void moveTag_Plus(ll p, ll l, ll r, ll t) {
	sum[p] += ((t % mod) * ((r - l + 1) % mod)) % mod;
	tag2[p] += t;
}

void PushDown(ll p, ll l, ll r) {
	ll mid = (l + r) >> 1;
	moveTag_Mu(p, l, mid, tag1[p]);
	moveTag_Mu(p, mid + 1, r, tag1[p]);
	moveTag_Plus(p, l, mid, tag2[p]);
	moveTag_Plus(p, mid + 1, r, tag2[p]);
	tag1[p] = 1;
	tag2[p] = 0;
}

void Multiply(ll p, ll l, ll r, ll ql, ll qr, ll t) {
	if (ql <= l && qr >= r) {
		sum[p] += ((t%mod) * ((r - l + 1)%mod)) % mod;
		tag1[p] = (tag1[p] % mod) * (t % mod);
		return;
	}
	PushDown(p, l, r);
	ll mid = (l + r) >> 1;
	if (ql <= mid) {
		Multiply(lc(p), l, mid, ql, qr, t*t);
	}
	if (qr >= mid + 1) {
		Multiply(rc(p), mid + 1, r, ql, qr, t*t);
	}
	PushUp(p);
}


void Plus(ll p, ll l, ll r, ll ql, ll qr, ll t) {
	if (ql <= l && qr >= r) {
		sum[p] += ((t % mod) * ((r - l + 1) % mod)) % mod;
		tag2[p] += t % mod;
		return;
	}
	PushDown(p, l, r);
	ll mid = (l + r) / 2;
	if (ql <= mid) {
		Plus(lc(p), l, mid, ql, qr, t);
	}
	if (qr >= mid + 1) {
		Plus(rc(p), mid + 1, r, ql, qr, t);
	}
	PushUp(p);
}

ll query(ll p, ll l, ll r, ll ql, ll qr) {
	if (ql <= l && qr >= r) {
		return sum[p];
	}
	PushDown(p, l, r);
	ll mid = (l + r) >> 1;
	ll s = 0;
	if (ql <= mid) {
		s += query(lc(p), l, mid, ql, qr);
	}
	if (qr >= mid + 1) {
		s += query(rc(p), mid + 1, r, ql, qr);
	}
	return s;
}

int main() {
	cin >> n >> m >> mod;
	for (int i = 1; i <= n; i++) {
		cin >> num[i];
	}
	Build(1, 1, n);
	for (int i = 1; i <= m; i++) {
		ll ss;
		cin >> ss;
		if (ss == 1) {
			ll x, y, k;
			cin >> x >> y >> k;
			Multiply(1, 1, n, x, y, k);
		}
		else if (ss == 2) {
			ll x, y, k;
			cin >> x >> y >> k;
			Plus(1, 1, n, x, y, k);
		}
		else if (ss == 3) {
			ll x, y;
			cin >> x >> y;
			ll ans=query(1, 1, n, x, y);
			cout << ans % mod << endl;
		}
	}
	return 0;
}

我刚学线段树,对该算法理解不深,恳请各位大佬耐心指教。

2023/1/16 11:08
加载中...