P3373 【模板】线段树 2
题目描述
如题,已知一个数列 a,你需要进行下面三种操作:
- 将某区间每一个数乘上 x;
- 将某区间每一个数加上 x;
- 求出某区间每一个数的和。
输入格式
第一行包含三个整数 n,q,m,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值 ai。
接下来 q 行每行包含若干个整数,表示一个操作,具体如下:
操作 1: 格式:1 x y k
含义:将区间 [x,y] 内每个数乘上 k。
操作 2: 格式:2 x y k
含义:将区间 [x,y] 内每个数加上 k。
操作 3: 格式:3 x y
含义:输出区间 [x,y] 内每个数的和对 m 取模所得的结果。
输出格式
输出包含若干行整数,即为所有操作 3 的结果。
输入输出样例
输入 #1
5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4
输出 #1
17 2
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<set>
#include<map>
#include<unordered_set>
#include<unordered_map>
#include<bitset>
#include<tuple>
#define inf 72340172838076673
#define int long long
#define endl '\n'
#define F first
#define S second
#define mst(a,x) memset(a,x,sizeof (a))
using namespace std;
typedef pair<int, int> pii;const int N = 200086;int n, m, mod;
int w[N];struct node {int l, r;int s;int add, mul;
} e[N * 4];void pushdown(int u) {node& root = e[u], &lf = e[u << 1], &ri = e[u << 1 | 1];lf.s = (lf.s * root.mul + (lf.r - lf.l + 1) * root.add) % mod;ri.s = (ri.s * root.mul + (ri.r - ri.l + 1) * root.add) % mod;lf.mul = (lf.mul * root.mul) % mod;ri.mul = (ri.mul * root.mul) % mod;lf.add = (lf.add * root.mul + root.add) % mod;ri.add = (ri.add * root.mul + root.add) % mod;root.add = 0, root.mul = 1;
}void pushup(int u) {e[u].s = e[u << 1].s + e[u << 1 | 1].s;
}void build(int u, int l, int r) {if (l == r) e[u] = {l, r, w[l], 0, 1};else {e[u] = {l, r, 0, 0, 1};int mid = l + r >> 1;build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);pushup(u);}
}void modify(int u, int l, int r, int v, int k) {if (l <= e[u].l && e[u].r <= r) {if (k == 1) {e[u].mul = (e[u].mul * v) % mod;e[u].add = (e[u].add * v) % mod;e[u].s = (e[u].s * v) % mod;} else {e[u].add = (e[u].add + v) % mod;e[u].s = (e[u].s + (e[u].r - e[u].l + 1) * v) % mod;}} else {pushdown(u);int mid = e[u].l + e[u].r >> 1;if (l <= mid) modify(u << 1, l, r, v, k);if (r > mid) modify(u << 1 | 1, l, r, v, k);pushup(u);}}int query(int u, int l, int r) {if (l <= e[u].l && e[u].r <= r) return e[u].s % mod;pushdown(u);int mid = e[u].l + e[u].r >> 1;int res = 0;if (l <= mid) res = query(u << 1, l, r);if (r > mid) res += query(u << 1 | 1, l, r);return res % mod;
}void solve() {cin >> n >> m >> mod;for (int i = 1; i <= n; i++) cin >> w[i];build(1, 1, n);while (m--) {int op, l, r, v;cin >> op >> l >> r;if (op == 3) cout << query(1, l, r) % mod << endl;else {cin >> v;modify(1, l, r, v, op);}}}signed main() {ios::sync_with_stdio(false);cin.tie(nullptr), cout.tie(nullptr);int T = 1;
// cin >> T;while (T--) solve();return 0;
}