DESTRUCTION_3_2_1 @ 2022-12-01 23:05:52
// Problem: P3373 【模板】线段树 2
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3373
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define int __int128
#define double long double
#define RE register
#define endl putchar('\n')
#define mp make_pair
#define pr pair < int , int >
#define It iterator
#define NF string::npos // NT --> NOT_FOUND
#define swap(x, y) (x ^= y ^= x ^= y)
#define max(x, y) (x > y ? x : y)
#define min(x, y) (x < y ? x : y)
#define ls (p << 1) // x * 2
#define rs (p << 1 | 1) // x * 2 + 1
using namespace std;
const int INF = 2147483647;
const int SZ = 1e5 + 5;
int n, m, mod, sum[SZ << 2], mul[SZ << 2], tag[SZ << 2], a[SZ], l, r, k, opt;
// 变量
inline int read() {
RE int X=0,w=0; RE char ch=0;
while (!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while (isdigit(ch)) { X = (X << 3) + (X << 1) + (ch ^ 48); ch = getchar(); }
return w ? -X : X; }
inline void write(int x) {
if (x < 0) { x = ~x + 1; putchar('-'); }
if(x > 9) write(x / 10);
putchar(x % 10 + '0'); }
// 函数
inline void pushUp (int p) {
sum[p] = sum[ls] + sum[rs];
sum[p] %= mod;
}
inline void pushDown (int p, int s, int t) {
int mid = s + ((t - s) >> 1);
if (mul[p] != 1) {
// *
mul[ls] *= mul[p]; mul[rs] *= mul[p];
sum[ls] *= mul[p]; sum[rs] *= mul[p];
tag[ls] *= mul[p]; tag[rs] *= mul[p];
// %
mul[ls] %= mod; mul[rs] %= mod;
sum[ls] %= mod; sum[rs] %= mod;
tag[ls] %= mod; tag[rs] %= mod;
mul[p] = 1;
}
if (tag[p]) {
// +
sum[ls] += tag[p] * (mid - s + 1); sum[rs] += tag[p] * (t - mid);
tag[ls] += tag[p]; tag[rs] += tag[p];
// %
sum[ls] %= mod; sum[rs] %= mod;
tag[ls] %= mod; tag[rs] %= mod;
tag[p] = 0;
}
}
inline void build (int p, int s, int t) {
mul[p] = 1;
if (s == t) {
sum[p] = a[s];
return;
}
int mid = s + ((t - s) >> 1);
build(ls, s, mid);
build(rs, mid + 1, t);
pushUp(p);
}
inline void add_mul (int p, int l, int r, int s, int t, int k) {
if (l <= s && t <= s) {
mul[p] *= k; sum[p] *= k; tag[p] *= k;
mul[p] %= mod; sum[p] %= mod; tag[p] %= mod;
return;
}
pushDown(p, s, t);
int mid = s + ((t - s) >> 1);
if (mid >= l) add_mul (ls, l, r, s, mid, k);
if (mid + 1 <= r) add_mul (rs, l, r, mid + 1, t, k);
pushUp(p);
}
inline void add_sum (int p, int l, int r, int s, int t, int k) {
if (l <= s && t <= r) {
tag[p] += k; tag[p] %= mod;
sum[p] += k * (t - s + 1); sum[p] %= mod;
return;
}
pushDown(p, s, t);
int mid = s + ((t - s) >> 1);
if (mid >= l) add_sum (ls, l, r, s, mid, k);
if (mid + 1 <= r) add_sum (rs, l, r, mid + 1, t, k);
pushUp(p);
}
inline int getans (int p, int l, int r, int s, int t) {
if (l <= s && t <= r) return sum[p];
pushDown(p, s, t);
int mid = s + ((t - s) >> 1), ans = 0;
if (mid >= l) ans += getans(ls, l, r, s, mid);
if (mid + 1 <= r) ans += getans(rs, l, r, mid + 1, t);
return ans % mod;
}
signed main(void)
{
//freopen("input.in","r",stdin);
//freopen("output.out","w",stdout);
n = read(); m = read(); mod = read();
for (int i = 1; i <= n; i++) a[i] = read();
build(1, 1, n);
for (int i = 1; i <= m; i++) {
opt = read();
if (opt == 1) {
l = read(); r = read(); k = read();
add_mul(1, l, r, 1, n, k);
}
if (opt == 2) {
l = read(); r = read(); k = read();
add_sum(1, l, r, 1, n, k);
}
if (opt == 3) {
l = read(); r = read();
write(getans(1, l, r, 1, n));
endl;
}
}
//fclose(stdin);
//fclose(stdout);
return 0;
}
1.为什么会T
2.求取余时间复杂
by DESTRUCTION_3_2_1 @ 2022-12-01 23:07:38
题错了,应该是模板2
by DESTRUCTION_3_2_1 @ 2022-12-01 23:08:51
评测记录
by too_simple @ 2022-12-02 06:57:06
@Dyc大大吖 您为啥要把线段树2的模板贺到线段树1里呢?
by too_simple @ 2022-12-02 07:00:16
你取模不影响复杂度(应该,但你为啥要取模呢?
by reveal @ 2022-12-02 08:22:40
inline void add_mul (int p, int l, int r, int s, int t, int k) {
if (l <= s && t <= s) { // 这是不是写错了,明显是 l <= s && t <= r
by DESTRUCTION_3_2_1 @ 2022-12-02 10:45:57
@reveal 我是sb