Files
python/TangDou/AcWing/SegmentTree/T125847.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

86 lines
2.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 1e7 + 10;
typedef long long LL;
int m, p; // m个输入,p是模的值
// 动态开点线段树
#define ls tr[u].l
#define rs tr[u].r
#define mid ((l + r) >> 1)
struct Node {
int l, r;
int sum, add;
} tr[N << 1];
int root, idx;
// 根节点编号,初始值是0,通过modify创建,第1个,也就是根root=1
// idx:节点号游标
// 汇总统计信息
void pushup(int u) {
tr[u].sum = (LL(tr[ls].sum) + LL(tr[rs].sum)) % p;
}
void pushdown(int &u, int l, int r) {
if (tr[u].add == 0) return; // 如果没有累加懒标记,返回
if (ls == 0) ls = ++idx; // 左儿子创建
if (rs == 0) rs = ++idx; // 右儿子创建
// 懒标记下传
tr[ls].sum = (LL(tr[ls].sum) + LL(tr[u].add) * (mid - l + 1) % p) % p; // 区间和增加=懒标记 乘以 区间长度
tr[rs].sum = (LL(tr[rs].sum) + LL(tr[u].add) * (r - mid) % p) % p;
tr[ls].add = (LL(tr[ls].add) + LL(tr[u].add)) % p; // 加法的懒标记可以叠加
tr[rs].add = (LL(tr[rs].add) + LL(tr[u].add)) % p;
// 清除懒标记
tr[u].add = 0;
}
// 区间修改
void modify(int &u, int l, int r, int L, int R, int v) {
if (u == 0) u = ++idx; // 动态开点
if (l >= L && r <= R) { // 如果区间被完整覆盖
tr[u].add = (LL(tr[u].add) + v) % p; // 加法的懒标记可以叠加
tr[u].sum = (LL(tr[u].sum) % p + LL(v) * (r - l + 1) % p) % p; // 区间和增加=懒标记 乘以 区间长度
// cout << tr[u].add << " " << tr[u].sum << endl;
return;
}
if (l > R || r < L) return; // 如果没有交集
// 下传懒标记
pushdown(u, l, r);
// 分裂
modify(ls, l, mid, L, R, v), modify(rs, mid + 1, r, L, R, v);
// 汇总
pushup(u);
}
// 区间查询
LL query(int u, int l, int r, int L, int R) {
if (l >= L && r <= R) return tr[u].sum % p; // 如果完整命中,返回我的全部
if (l > R || r < L) return 0; // 如果与我无关,返回0
pushdown(u, l, r);
return (query(ls, l, mid, L, R) + query(rs, mid + 1, r, L, R)) % p;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("T125847.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
cin >> m >> p;
while (m--) {
int op, x, y, k;
cin >> op >> x >> y;
if (op == 1) {
cin >> k;
modify(root, 1, 1000000000, x, y, k);
} else
cout << query(root, 1, 1000000000, x, y) % p << endl;
}
return 0;
}