6:
LAZY 线段树有乘法的更新
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn = 101000;
long long value[maxn], mod;
struct SegNode {
int left, right;
long long sum, add, mul;
int mid() {
return (left + right) >> 1;
}
int size() {
return right - left + 1;
}
};
struct SegmentTree {
SegNode tree[maxn*5];
void pushUp(int idx) {
tree[idx].sum = (tree[idx<<1].sum + tree[idx<<1|1].sum) % mod;
}
void pushDown(int idx) {
tree[idx<<1].add = (tree[idx].mul % mod * tree[idx<<1].add % mod + tree[idx].add) % mod;
tree[idx<<1|1].add = (tree[idx].mul % mod * tree[idx<<1|1].add % mod + tree[idx].add) % mod;
tree[idx<<1].mul = tree[idx<<1].mul % mod * tree[idx].mul % mod;
tree[idx<<1|1].mul = tree[idx<<1|1].mul % mod * tree[idx].mul % mod;
tree[idx<<1].sum = (tree[idx<<1].sum % mod * tree[idx].mul % mod
+ tree[idx<<1].size() * tree[idx].add % mod) % mod;
tree[idx<<1|1].sum = (tree[idx<<1|1].sum % mod * tree[idx].mul % mod
+ tree[idx<<1|1].size() * tree[idx].add % mod) % mod;
tree[idx].add = 0;
tree[idx].mul = 1;
}
void build(int left, int right, int idx) {
tree[idx].left = left;
tree[idx].right = right;
tree[idx].sum = 0;
tree[idx].mul = 1;
tree[idx].add = 0;
if (left == right) {
tree[idx].sum = value[left] % mod;
return ;
}
int mid = tree[idx].mid();
build(left, mid, idx<<1);
build(mid+1, right, idx<<1|1);
pushUp(idx);
}
void update(int left, int right, int idx, int opt, long long val) {
if (tree[idx].left == left && tree[idx].right == right) {
if (opt == 1) {
tree[idx].add = (tree[idx].add + val) % mod;
tree[idx].sum = (tree[idx].sum + tree[idx].size() % mod * val) % mod;
} else {
tree[idx].add = tree[idx].add % mod * val % mod;
tree[idx].mul = tree[idx].mul % mod * val % mod;
tree[idx].sum = tree[idx].sum % mod * val % mod;
}
return ;
}
pushDown(idx);
int mid = tree[idx].mid();
if (right <= mid)
update(left, right, idx<<1, opt, val);
else if (left > mid)
update(left, right, idx<<1|1, opt, val);
else {
update(left, mid, idx<<1, opt, val);
update(mid+1, right, idx<<1|1, opt, val);
}
pushUp(idx);
}
long long query(int left, int right, int idx) {
if (tree[idx].left == left && tree[idx].right == right) {
return tree[idx].sum % mod;
}
pushDown(idx);
int mid = tree[idx].mid();
if (right <= mid)
return query(left, right, idx<<1);
else if (left > mid)
return query(left, right, idx<<1|1);
else {
return (query(left, mid, idx<<1) % mod + query(mid+1, right, idx<<1|1));
}
}
};
SegmentTree tree;
int n, m;
void init() {
scanf("%d %lld", &n, &mod);
for (int i = 1; i <= n; i++)
scanf("%lld", &value[i]);
tree.build(1, n, 1);
}