自己用函数包装了一下,多加了一个参数来区分乘法和加法的修改,但不知道为什么只有30分,过了1,3,4,那位大佬来看看QAQ
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int p = 1e5+10;
//P3373
int tree[p << 2],a[p],n,m,t,tag1[p<<2],tag2[p<<2],mod;
int ls(int x) { return x << 1; }
int rs(int x) { return x << 1|1; }
void push_up(int x) {
tree[x] = (tree[ls(x)] + tree[rs(x)])%mod;
}
void build(int x,int l,int r) {
tag1[x] = 1;
tag2[x] = 0;
if (l == r) {
tree[x] = a[l];
return;
}
int mid = (l + r) >> 1;
build(ls(x), l, mid);
build(rs(x), mid + 1, r);
push_up(x);
}
void addtag(int x,int l,int r,int w,int k) {
if (k == 1) {//乘法
tag2[x] = (tag2[x] * w) % mod;
tag1[x] = (tag1[x] * w) % mod;
tree[x] = (tree[x] * w) % mod;
}
else {//加法
tag2[x] = (tag2[x] + w) % mod;
tree[x] = (tree[x] + (r - l + 1) * w) % mod;
}
}
void push_down(int x, int l, int r) {
if (tag1[x]>1) {//乘法标记
int mid = (l + r) >> 1;
addtag(ls(x), l, mid,tag1[x],1);
addtag(rs(x), mid + 1, r, tag1[x],1);
tag1[x] = 1;
}
if (tag2[x]) {//加法标记
int mid = (l + r) >> 1;
addtag(ls(x), l, mid, tag2[x],2);
addtag(rs(x), mid + 1, r, tag2[x],2);
tag2[x] = 0;
}
}
void update(int L, int R, int x, int l, int r, int w, int k) {
if (L <= l && r <= R) {
addtag(x, l, r, w, k);
return;
}
push_down(x, l, r);
int mid = (l + r) >> 1;
if (L <= mid)update(L, R, ls(x), l, mid, w, k);
if (R > mid)update(L, R, rs(x), mid + 1, r, w, k);
push_up(x);
}
int query(int L, int R, int x, int l, int r) {
if (L <= l && r <= R) return tree[x];
push_down(x, l, r);
int res = 0;
int mid = (l + r) >> 1;
if (L <= mid)res = (res + query(L, R, ls(x), l, mid)) % mod;
if (R > mid)res = (res + query(L, R, rs(x), mid + 1, r)) % mod;
return res%mod;
}
signed main() {
cin >> n >> m >> mod;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
build(1, 1, n);
int op, x, y, k;
while (m--) {
cin >> op;
if (op == 1) {
cin >> x >> y >> k;
update(x, y, 1, 1, n, k, op);
}
else if (op == 2) {
cin >> x >> y >> k;
update(x, y, 1, 1, n, k, op);
}
else {
cin >> x >> y;
cout << query(x, y, 1, 1, n) << endl;
}
}
}