蒟蒻re求条,难崩!!!
查看原帖
蒟蒻re求条,难崩!!!
1140231
ChangeYuAN楼主2024/8/11 17:38
#include <bits/stdc++.h>
using namespace std;
const int MAXLEN = 1e5 + 5;
#define int long long
int n, q, mod, a[MAXLEN];

struct Segment_Tree {
	int tag_a, tag_m, sum; //加标记、乘标记、和
	int l, r; //左端点、右端点
} t[MAXLEN << 2];

void pushup(int x) {
	t[x].sum = (t[x << 1].sum + t[x << 1 | 1].sum) % mod;
	return ;
}

void pushdown(int x) { //传下标记
	//维护sum
	t[x << 1].sum = (t[x << 1].sum * t[x].tag_m + t[x].tag_a * (t[x << 1].r - t[x << 1].l + 1))%mod;
	t[x << 1 | 1].sum = (t[x << 1 | 1].sum * t[x].tag_m + t[x].tag_a * (t[x << 1 | 1].r - t[x << 1 | 1].l + 1))%mod;
	//乘标记tag_m
	t[x << 1].tag_m = (t[x].tag_m * t[x << 1].tag_m) % mod;
	t[x << 1 | 1].tag_m = (t[x].tag_m * t[x << 1 | 1].tag_m) % mod;
	//加标记tag_a
	t[x << 1].tag_a = (t[x << 1].tag_a * t[x].tag_m + t[x].tag_a) % mod;
	t[x << 1 | 1].tag_a = (t[x << 1 | 1].tag_a * t[x].tag_m + t[x].tag_a) % mod;
	//标记已传下,返回初始状态
	t[x].tag_a = 0;
	t[x].tag_m = 1;
	return ;
}

void build(int x, int l, int r) { //建树
	int mid = (l + r) >> 1;
	//初始化l,r,标记
	t[x].l = l;
	t[x].r = r;
	t[x].tag_m = 1;
	if (l == r) { //已到达叶子节点,初始化t[x].sum=a[l(r)];
		t[x].sum = a[l] % mod;
		return ;
	}
	build(x << 1, l, mid); //递归左子树
	build(x << 1 | 1, mid + 1, r); //递归右子树
	pushup(x);//回溯,更新区间和
	return ;
}

void makeaddtag(int x, int len, int dlt) { //建立加标记
	t[x].sum = (t[x].sum + len * dlt) % mod; //维护区间和
	t[x].tag_a = (t[x].tag_a + dlt) % mod;
	return ;
}

void makemultitag(int x, int dlt) { //建立乘标记
	t[x].sum = (t[x].sum * dlt) % mod; //同上
	t[x].tag_m = (t[x].tag_m * dlt) % mod;
	t[x].tag_a = (t[x].tag_a * dlt) % mod;
	return ;
}

void changeadd(int x, int l, int r, int cl, int cr, int dlt) { //区间加
	if (cl <= l && r <= cr) { //本区间完全包括在修改区间内
		makeaddtag(x, r - l + 1, dlt); //加标记
		return ;
	}
	pushdown(x);//传下标记
	int mid = (l + r) >> 1;
	if (l <= mid)
		changeadd(x << 1, l, mid, cl, cr, dlt); //递归左子树
	if (r > mid)
		changeadd(x << 1 | 1, mid + 1, r, cl, cr, dlt); //递归右子树
	pushup(x);//更新sum
	return ;
}

void changemulti(int x, int l, int r, int cl, int cr, int dlt) { //区间乘
	if (cl <= l && r <= cr) { //同上
		makemultitag(x, dlt);
		return ;
	}
	pushdown(x);//传下标记
	int mid = (l + r) >> 1;
	if (l <= mid)
		changemulti(x << 1, l, mid, cl, cr, dlt); //递归修改左子树
	if (r > mid)
		changemulti(x << 1 | 1, mid + 1, r, cl, cr, dlt); //递归修改右子树
	pushup(x);//更新sum
	return ;
}

int query(int x, int l, int r, int ql, int qr) {
	if (ql<=l&& r <= qr) { //同上
		return t[x].sum;
	}
	pushdown(x);
	int ret = 0;
	int mid = (l + r) >> 1;
	if (l <= mid)
		ret = (ret + query(x << 1, l, mid, ql, qr)) % mod; //递归左子树
	if (r > mid)
		ret = (ret + query(x << 1 | 1, mid + 1, r, ql, qr)) % mod; //递归右子树
	return ret;
}

signed main() {
	scanf("%lld%lld%lld", &n, &q, &mod);
	for (int i = 1; i <= n; i++)
		scanf("%lld", &a[i]);
	build(1, 1, n);
	for (int i = 1; i <= q; i++) {
		long long x, y, k;
		int opt;
		scanf("%lld%lld%lld", &opt, &x, &y);
		if (opt == 1) {
			scanf("%lld", &k);
			changemulti(1, 1, n, x, y, k);
		}
		if (opt == 2) {
			scanf("%lld", &k);
			changeadd(1, 1, n, x, y, k);
		}
		if (opt == 3) {
			printf("%lld", query(1, 1, n, x, y));
			puts("");
		}
	}
}
2024/8/11 17:38
加载中...