https://www.luogu.org/problemnew/show/P3373
如题,已知一个数列,你需要进行下面三种操作:
1.将某区间每一个数乘上x
2.将某区间每一个数加上x
3.求出某区间每一个数的和
#include<bits/stdc++.h>
#optimaze
using namespace std;
typedef long long ll;
const int maxn = 100000 + 5;
ll tre[maxn << 2], lzyadd[maxn << 2], lzymup[maxn << 2];
int x, n, m, p;
void push_up(int rt) {
tre[rt] = (tre[rt << 1] + tre[rt << 1 | 1]) % p;
}
void push_down(int rt, int l, int r) {
if(lzyadd[rt] == 0 && lzymup[rt] == 1) return;
int mid = l + r >> 1;
tre[rt << 1] = (tre[rt << 1] * lzymup[rt] + (mid - l + 1) * lzyadd[rt]) % p;
tre[rt << 1 | 1] = (tre[rt << 1 | 1] * lzymup[rt] + (r - mid) * lzyadd[rt]) % p;
lzymup[rt << 1] = lzymup[rt << 1] * lzymup[rt] % p;
lzymup[rt << 1 | 1] = lzymup[rt << 1 | 1] * lzymup[rt] % p;
lzyadd[rt << 1] = (lzyadd[rt << 1] * lzymup[rt] + lzyadd[rt]) % p;
lzyadd[rt << 1 | 1] = (lzyadd[rt << 1 | 1] * lzymup[rt] + lzyadd[rt]) % p;
lzyadd[rt] = 0;
lzymup[rt] = 1;
return;
}
void build(int rt, int l, int r) {
lzyadd[rt] = 0;
lzymup[rt] = 1;
if(l == r) {
cin >> tre[rt];
tre[rt] = tre[rt] % p;
return;
}
int mid = l + r >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
push_up(rt);
}
void update(int rt, int l, int r, int L, int R, bool op, int x) {
if(L <= l && r <= R) {
if(op) {
tre[rt] = tre[rt] * x % p;
lzymup[rt] = lzymup[rt] * x % p;
lzyadd[rt] = lzyadd[rt] * x % p;
}
else {
lzyadd[rt] = (lzyadd[rt] + x) % p;
tre[rt] = (tre[rt] + (r - l + 1) * x) % p;
}
return;
}
push_down(rt, l, r);
int mid = l + r >> 1;
if(L <= mid) update(rt << 1, l, mid, L, R, op, x);
if(mid < R) update(rt << 1 | 1, mid + 1, r, L, R, op, x);
push_up(rt);
}
ll query(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) return tre[rt];
push_down(rt, l, r);
int mid = l + r >> 1;
ll res = 0;
if(L <= mid) res = (res % p + query(rt << 1, l, mid, L, R) % p) % p;
if(R > mid) res = (res % p + query(rt << 1 | 1, mid + 1, r, L, R) % p) % p;
push_up(rt);
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> p;
build(1, 1, n);
int op, x, y, z;
while(m--) {
cin >> op;
if(op == 1) {
cin >> x >> y >> z;
update(1, 1, n, x, y, 1, z);
}
else if(op == 2) {
cin >> x >> y >> z;
update(1, 1, n, x, y, 0, z);
}
else if(op == 3) {
cin >> x >> y;
cout << query(1, 1, n, x, y) << endl;
}
}
}