https://www.acwing.com/solution/content/245700/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int n, m, w[N], mod;
struct Node { int l, r, sum; } tr[N << 2];
struct Tag { int mul,add; } tag[N << 2];
Node pushup(Node a, Node b)
{
return {a.l, b.r, (a.sum + b.sum) % mod};
}
int len(Node a) { return a.r - a.l + 1; }
Node BrushAndTag(int u, Tag v)
{
tr[u].sum = ((LL)tr[u].sum * v.mul % mod + (LL)v.add * len(tr[u])) % mod;
tag[u].mul = ((LL) tag[u].mul * v.mul) % mod;
tag[u].add = ((LL)tag[u].add * v.mul + v.add) % mod;
return tr[u];
}
void pushdown(int u)
{
BrushAndTag(u << 1, tag[u]);
BrushAndTag(u << 1 | 1, tag[u]);
tag[u] = {1, 0};
}
Node build(int u, int l, int r)
{
tag[u] = {1, 0};
if (l == r) return tr[u] = {l, r, w[r] % mod};
int mid = (l + r) >> 1;
return tr[u] = pushup(build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r));
}
Node modify(int u, int l, int r, Tag v)
{
if (tr[u].r < l || tr[u].l > r) return tr[u];
if (tr[u].l >= l && tr[u].r <= r) return tr[u] = BrushAndTag(u, v);
pushdown(u);
return tr[u] = pushup(modify(u << 1, l, r, v), modify(u << 1 | 1, l, r, v));
}
Node query(int u, int l, int r)
{
if (!tr[u].l) return tr[0];
if (tr[u].r < l || tr[u].l > r) return tr[0];
if (tr[u].l >= l && tr[u].r <= r) return tr[u];
pushdown(u);
return pushup(query(u << 1, l, r), query(u << 1 | 1, l, r));
}
int main()
{
scanf("%d%d", &n, &mod);
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
build(1, 1, n);
scanf("%d", &m);
while (m -- )
{
int t, a, b, c;
scanf("%d%d%d", &t, &a, &b);
if (t == 1)
{
scanf("%d", &c);
modify(1, a, b, {c, 0});
}
else if (t == 2)
{
scanf("%d", &c);
modify(1, a, b, {1, c});
}
else printf("%d\n", query(1, a, b).sum);
}
return 0;
}
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int N = 500010;
int n, m;
LL w[N];
struct Node
{
int l, r;
LL sum;
LL d;
}tr[N << 2];
LL gcd(LL a, LL b)
{
return b ? gcd(b, a % b) : a;
}
void pushup(Node& u, Node& l, Node& r)
{
u.sum = l.sum + r.sum;
u.d = gcd(l.d, r.d);
}
void pushup(int u)
{
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
void build(int u, int l, int r)
{
if (l == r)
{
LL b = w[r] - w[r - 1];
tr[u] = {l, r, b, b};
}
else
{
tr[u].l = l, tr[u].r = r;
int mid = (l + r) >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int x, LL v)
{
if (tr[u].l == x && tr[u].r == x)
{
LL b = tr[u].sum + v;
tr[u] = {x, x, b, b};
}
else
{
int mid = (tr[u].l + tr[u].r) >> 1;
if (x <= mid) modify(u << 1, x, v);
else modify(u << 1 | 1, x, v);
pushup(u);
}
}
Node query(int u, int l, int r)
{
//if (l > r) return {0};
if (tr[u].l >= l && tr[u].r <= r) return tr[u];
else
{
int mid = (tr[u].l + tr[u].r) >> 1;
if (r <= mid) return query(u << 1, l, r);
else if (l > mid) return query(u << 1 | 1, l, r);
else
{
auto left = query(u << 1, l, r);
auto right = query(u << 1 | 1, l, r);
Node res;
pushup(res, left, right);
return res;
}
}
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%lld", &w[i]);
build(1, 1, n);
char op[2];
int l, r;
LL v;
while (m -- )
{
scanf("%s%d%d", op, &l, &r);
if (*op == 'Q')
{
auto left = query(1, 1, l);
Node right({0, 0, 0, 0});
if (l + 1 <= r) right = query(1, l + 1, r);
printf("%lld\n", abs(gcd(left.sum, right.d)));
}
else
{
scanf("%lld", &v);
modify(1, l, v);
if (r + 1 <= n) modify(1, r + 1, -v);
}
}
return 0;
}