线段树求调(调好必关)
查看原帖
线段树求调(调好必关)
690561
违规用户名690561楼主2024/8/7 19:18
#include<bits/stdc++.h>
using namespace std;
long long n, q, m, a[400005], _, x, y, k;
long long d[400005], t1[400005], t2[400005];
void build(long long l, long long r, long long p) {
	if(l == r) {
		d[p] = a[l];
		d[p] %= m;
		return;
	}
	long long mid = (l + r) / 2;
	build(l, mid, p * 2);
	build(mid + 1, r, p * 2 + 1);
	d[p] = d[p * 2] + d[p * 2 + 1];
	d[p] %= m;
	return;
}
void add1(long long l, long long r, long long p) {
	if(x <= l && r <= y) {
		d[p] *= k;
		d[p] %= m;
		t1[p] *= k;
		t1[p] %= m;
		t2[p] *= k;
		t2[p] %= m;
		return;
	}
	long long mid = (l + r) / 2;
	if(t1[p] != 1 && l != r) {
		d[p * 2] *= t1[p];
		d[p * 2] %= m;
		d[p * 2 + 1] *= t1[p];
		d[p * 2 + 1] %= m;
		t1[p * 2] *= t1[p];
		t1[p * 2] %= m;
		t1[p * 2 + 1] *= t1[p];
		t1[p * 2 + 1] %= m;
		t1[p] = 1;
	}
	if(t2[p] != 0 && l != r) {
		d[p * 2] += t2[p] * (mid - l + 1);
		d[p * 2] %= m;
		d[p * 2 + 1] += t2[p] * (r - mid);
		d[p * 2 + 1] %= m;
		t2[p * 2] += t2[p];
		t2[p * 2] %= m;
		t2[p * 2 + 1] += t2[p];
		t2[p * 2 + 1] %= m;
		t2[p] = 0;
	}
	if(x <= mid) {
		add1(x, mid, p * 2);
	}
	if(mid + 1 <= y) {
		add1(mid + 1, y, p * 2 + 1);
	}
	d[p] = d[p * 2] + d[p * 2 + 1];
	d[p] %= m;
	return;
}
void add2(long long l, long long r, long long p) {
	if(x <= l && r <= y) {
		d[p] += (r - l + 1) * k;
		d[p] %= m;
		t2[p] += k;
		t2[p] %= m;
		return;
	}
	long long mid = (l + r) / 2;
	if(t1[p] != 1 && l != r) {
		d[p * 2] *= t1[p];
		d[p * 2] %= m;
		d[p * 2 + 1] *= t1[p];
		d[p * 2 + 1] %= m;
		t1[p * 2] *= t1[p];
		t1[p * 2] %= m;
		t1[p * 2 + 1] *= t1[p];
		t1[p * 2 + 1] %= m;
		t1[p] = 1;
	}
	if(t2[p] != 0 && l != r) {
		d[p * 2] += t2[p] * (mid - l + 1);
		d[p * 2] %= m;
		d[p * 2 + 1] += t2[p] * (r - mid);
		d[p * 2 + 1] %= m;
		t2[p * 2] += t2[p];
		t2[p * 2] %= m;
		t2[p * 2 + 1] += t2[p];
		t2[p * 2 + 1] %= m;
		t2[p] = 0;
	}
	if(x <= mid) {
		add2(l, mid, p * 2);
	}
	if(mid + 1 <= y) {
		add2(mid + 1, r, p * 2 + 1);
	}
	d[p] = d[p * 2] + d[p * 2 + 1];
	d[p] %= m;
	return;
}
long long Find(long long l, long long r, long long p) {
	if(x <= l && r <= y) {
		return d[p];
	}
	long long sum = 0, mid = (l + r) / 2;
	if(t1[p] != 1 && l != r) {
		d[p * 2] *= t1[p];
		d[p * 2] %= m;
		d[p * 2 + 1] *= t1[p];
		d[p * 2 + 1] %= m;
		t1[p * 2] *= t1[p];
		t1[p * 2] %= m;
		t1[p * 2 + 1] *= t1[p];
		t1[p * 2 + 1] %= m;
		t1[p] = 1;
	}
	if(t2[p] != 0 && l != r) {
		d[p * 2] += t2[p] * (mid - l + 1);
		d[p * 2] %= m;
		d[p * 2 + 1] += t2[p] * (r - mid);
		d[p * 2 + 1] %= m;
		t2[p * 2] += t2[p];
		t2[p * 2] %= m;
		t2[p * 2 + 1] += t2[p];
		t2[p * 2 + 1] %= m;
		t2[p] = 0;
	}
	if(x <= mid) {
		sum += Find(l, mid, p * 2);
		sum %= m;
	}
	if(mid + 1 <= y) {
		sum += Find(mid + 1, r, p * 2 + 1);
		sum %= m;
	}
	return sum;
}
int main() {
	scanf("%lld %lld %lld", &n, &q, &m);
	for(long long i = 1; i <= 4 * n; i++) {
		t1[i] = 1;
	}
	for(long long i = 1; i <= n; i++) {
		scanf("%lld", &a[i]);
	}
	for(long long i = 1; i <= q; i++) {
		scanf("%lld", &_);
		if(_ == 1) {
			scanf("%lld %lld %lld", &x, &y, &k);
			add1(1, n, 1);
		} else if(_ == 2) {
			scanf("%lld %lld %lld", &x, &y, &k);
			add2(1, n, 1);
		} else {
			scanf("%lld %lld", &x, &y);
			printf("%lld\n", Find(1, n, 1) % m);
		}
	}
	return 0;
}

t1为乘法懒标记,t2为加法懒标记,add1处理乘法,add2处理加法。

2024/8/7 19:18
加载中...