You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.8 KiB

2 years ago
#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;
}