From 6e8778f275757cb4b2ead5490c9923d328b80b1b Mon Sep 17 00:00:00 2001 From: hanyixuanten Date: Wed, 28 Oct 2026 11:35:01 +0000 Subject: [PATCH] new file: P3373.cpp --- P3373.cpp | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ P3373.md | 66 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 P3373.cpp create mode 100644 P3373.md diff --git a/P3373.cpp b/P3373.cpp new file mode 100644 index 0000000..c8b6468 --- /dev/null +++ b/P3373.cpp @@ -0,0 +1,94 @@ +#include +using namespace std; +struct node { + long long sum; + long long lt1; + long long lt2 = 1; +} seg[400005]; +int n, q; +long long m; +int a[100005]; +void pu(int now) { + seg[now].sum = (seg[now * 2].sum + seg[now * 2 + 1].sum) % m; +} +void apply(int now, int len, long long mul, long long add) { + seg[now].sum = (seg[now].sum * mul % m + add * len % m) % m; + seg[now].lt2 = seg[now].lt2 * mul % m; + seg[now].lt1 = (seg[now].lt1 * mul % m + add) % m; +} +void pd(int now, int nl, int nr) { + if (seg[now].lt1 == 0 && seg[now].lt2 == 1) return; + int mid = (nl + nr) >> 1; + apply(now * 2, mid - nl + 1, seg[now].lt2, seg[now].lt1); + apply(now * 2 + 1, nr - mid, seg[now].lt2, seg[now].lt1); + seg[now].lt1 = 0; + seg[now].lt2 = 1; +} + +void init(int now, int nl, int nr) { + if (nl == nr) { + seg[now].sum = a[nl] % m; + return; + } + int mid = (nl + nr) >> 1; + init(now * 2, nl, mid); + init(now * 2 + 1, mid + 1, nr); + pu(now); +} +void add(int now, int nl, int nr, int l, int r, long long nn) { + if (nl > r || nr < l) return; + if (l <= nl && nr <= r) { + apply(now, nr - nl + 1, 1, nn % m); + return; + } + int mid = (nl + nr) >> 1; + pd(now, nl, nr); + add(now * 2, nl, mid, l, r, nn); + add(now * 2 + 1, mid + 1, nr, l, r, nn); + pu(now); +} +void mul(int now, int nl, int nr, int l, int r, long long nn) { + if (nl > r || nr < l) return; + if (l <= nl && nr <= r) { + apply(now, nr - nl + 1, nn % m, 0); + return; + } + int mid = (nl + nr) >> 1; + pd(now, nl, nr); + mul(now * 2, nl, mid, l, r, nn); + mul(now * 2 + 1, mid + 1, nr, l, r, nn); + pu(now); +} +long long query(int now, int nl, int nr, int l, int r) { + if (nl > r || nr < l) return 0; + if (l <= nl && nr <= r) { + return seg[now].sum % m; + } + int mid = (nl + nr) >> 1; + pd(now, nl, nr); + return (query(now * 2, nl, mid, l, r) + query(now * 2 + 1, mid + 1, nr, l, r)) % m; +} +int main() { + scanf("%d%d%lld", &n, &q, &m); + for (int i = 1; i <= n; ++i) { + scanf("%d", &a[i]); + } + init(1, 1, n); + while (q--) { + int op, x, y; + scanf("%d%d%d", &op, &x, &y); + if (op == 1) { + long long k; + scanf("%lld", &k); + mul(1, 1, n, x, y, k); + } else if (op == 2) { + long long k; + scanf("%lld", &k); + add(1, 1, n, x, y, k); + } else { + printf("%lld\n", query(1, 1, n, x, y)); + } + } + + return 0; +} \ No newline at end of file diff --git a/P3373.md b/P3373.md new file mode 100644 index 0000000..59e2b1a --- /dev/null +++ b/P3373.md @@ -0,0 +1,66 @@ +# P3373 【模板】线段树 2 + +## 题目描述 + +如题,已知一个数列 $a$,你需要进行下面三种操作: + +- 将某区间每一个数乘上 $x$; +- 将某区间每一个数加上 $x$; +- 求出某区间每一个数的和。 + +## 输入格式 + +第一行包含三个整数 $n,q,m$,分别表示该数列数字的个数、操作的总个数和模数。 + +第二行包含 $n$ 个用空格分隔的整数,其中第 $i$ 个数字表示数列第 $i$ 项的初始值 $a_i$。 + +接下来 $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 + +### 输入 #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 +``` + +## 说明/提示 + +【数据范围】 + +对于 $30\%$ 的数据:$n \le 8$,$q \le 10$。 +对于 $70\%$ 的数据:$n \le 10^3 $,$q \le 10^4$。 +对于 $100\%$ 的数据:$1 \le n \le 10^5$,$1 \le q \le 10^5,1\le a_i,k\le 10^4$。 + +除样例外,$m = 571373$。 + +(数据已经过加强 ^\_^) + +样例说明: + + ![](https://cdn.luogu.com.cn/upload/pic/2255.png) + +故输出应为 $17$、$2$($40 \bmod 38 = 2$)。 \ No newline at end of file