线段树 板子2 区间修改(加和乘)
作者:互联网
线段树
这两题本质一样,就放在一起
P2023 [AHOI2009] 维护序列
https://www.luogu.com.cn/problem/P2023
时刻%p; query也别忘了pushdown;打错就完蛋
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
int n, m, p;
LL a[N];
struct Node {
int l, r;
LL sum, add, mul;
}st[N * 4];
void pushup (int u) {
st[u].sum = (st[u << 1].sum + st[u << 1 | 1].sum) % p;
}
void pushdown (int u) {
auto &uu = st[u], &ll = st[u << 1], &rr = st[u << 1 | 1];
//更新lazy
ll.mul = (ll.mul * uu.mul) % p, ll.add = (ll.add * uu.mul + uu.add) % p;
rr.mul = (rr.mul * uu.mul) % p, rr.add = (rr.add * uu.mul + uu.add) % p;
//更新sum
ll.sum = (ll.sum * uu.mul + (ll.r - ll.l + 1) * uu.add) % p;
rr.sum = (rr.sum * uu.mul + (rr.r - rr.l + 1) * uu.add) % p; //一不小心打错就完蛋
//reset uu
uu.mul = 1, uu.add = 0;
}
void build (int u, int l, int r) {
if (l == r) {
st[u] = {l, r, a[r] % p, 0, 1};
return;
}
st[u] = {l, r}, st[u].mul = 1, st[u].add = 0;
int mid = l + r >> 1;
build (u << 1, l, mid);
build (u << 1 | 1, mid + 1, r);
pushup (u);
}
void modify_mul (int u, int l, int r, LL k) {
if (st[u].l >= l && st[u].r <= r) {
st[u].add = (st[u].add * k) % p;
st[u].mul = (st[u].mul * k) % p;
st[u].sum = (st[u].sum * k) % p;
return ;
}
pushdown (u);
int mid = st[u].l + st[u].r >> 1;
if (l <= mid)
modify_mul (u << 1, l, r, k);
if (r > mid)
modify_mul (u << 1 | 1, l, r, k);
pushup (u);
}
void modify_add (int u, int l, int r, LL k) {
if (st[u].l >= l && st[u].r <= r) {
st[u].add = (st[u].add + k) % p;
st[u].sum = (st[u].sum + (st[u].r - st[u].l + 1) * k) % p; //+=
return;
}
pushdown (u);
int mid = st[u].l + st[u].r >> 1;
if (l <= mid)
modify_add (u << 1, l, r, k);
if (r > mid)
modify_add (u << 1 | 1, l, r, k);
pushup (u);
}
LL query (int u, int l, int r) {
if (st[u].l >= l && st[u].r <= r) {
return st[u].sum % p;
}
pushdown (u);
LL res = 0;
int mid = st[u].l + st[u].r >> 1;
if (l <= mid)
res = (res + query (u << 1, l, r)) % p;
if (r > mid)
res = (res + query (u << 1 | 1, l, r)) % p;
return res;
}
int main () {
cin >> n >> p;
for (int i = 1; i <= n; i ++)
cin >> a[i];
cin >> m;
build (1, 1, n);
while (m --) {
int op, l, r, k;
cin >> op >> l >> r;
if (op == 1)
cin >> k, modify_mul (1, l, r, k);
else if (op == 2)
cin >> k, modify_add (1, l, r, k);
else
cout << query (1, l, r) % p << endl;
}
}
P3373 【模板】线段树 2
https://www.luogu.com.cn/problem/P3373
无处不在的细节问题,麻了。。。
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5 + 5;
typedef long long LL;
int n, m, p;
LL a[N];
struct Node {
int l, r;
LL sum, add, mul;
}st[N * 4];
void pushup (int u) {
st[u].sum = (st[u << 1].sum + st[u << 1 | 1].sum) % p;
}
void pushdown (int u) {
auto &uu = st[u], &ll = st[u << 1], &rr = st[u << 1 | 1];
//更新懒标记
ll.add = (LL)(ll.add * uu.mul + uu.add) % p, rr.add = (LL)(rr.add * uu.mul + uu.add) % p;
ll.mul *= uu.mul, rr.mul *= uu.mul; ll.mul %= p, rr.mul %= p;
//更新子树
ll.sum = (LL)(ll.sum * uu.mul + (LL)(ll.r - ll.l + 1) * uu.add) % p;
rr.sum = (LL)(rr.sum * uu.mul + (LL)(rr.r - rr.l + 1) * uu.add) % p;
//更新父懒标记
uu.mul = 1, uu.add = 0;
}
void build (int u, int l, int r) {
if (l == r) {
st[u] = {l, r, a[r] % p, 0, 1};
return;
}
st[u] = {l, r}; //又忘了!!
st[u].mul = 1;
int mid = l + r >> 1;
build (u << 1, l, mid);
build (u << 1 | 1, mid + 1, r);
pushup (u);
}
void modify_add (int u, int l, int r, LL v) {
if (st[u].l >= l && st[u].r <= r) {
st[u].add = (st[u].add + v) % p;
st[u].sum = (st[u].sum + (st[u].r - st[u].l + 1) * v) % p;
return;
}
pushdown (u);
int mid = st[u].l + st[u].r >> 1;
if (l <= mid)
modify_add (u << 1, l, r, v);
if (r > mid)
modify_add (u << 1 | 1, l, r, v);
pushup (u);
}
void modify_mul (int u, int l, int r, LL v) {
// if (v == 1)
// return;
if (st[u].l >= l && st[u].r <= r) {
st[u].add = (st[u].add * v) % p;
st[u].mul = (st[u].mul * v) % p;
st[u].sum = (st[u].sum * v) % p;
return ;
}
pushdown (u);
int mid = st[u].l + st[u].r >> 1;
if (l <= mid)
modify_mul (u << 1, l, r, v);
if (r > mid)
modify_mul (u << 1 | 1, l, r, v);
pushup (u);
}
LL query (int u, int l, int r) {
if (st[u].l >= l && st[u].r <= r) {
return st[u].sum % p;
}
pushdown (u);
LL res = 0;
int mid = st[u].l + st[u].r >> 1;
if (l <= mid)
res = (res + query (u << 1, l, r)) % p;
if (r > mid)
res = (res + query (u << 1 | 1, l, r)) % p;
return res % p;
}
int main () {
cin >> n >> m >> p;
for (int i = 1; i <= n; i ++)
cin >> a[i];
build (1, 1, n);
while (m --) {
int op, x, y, k;
cin >> op >> x >> y;
if (op == 3)
cout << query (1, x, y) % p << endl;
else if (op == 2)
cin >> k, modify_add (1, x, y, k);
else
cin >> k, modify_mul (1, x, y, k);
}
//主函数写错也是真无语
}
标签:int,线段,modify,cin,板子,op,st,LL,加和乘 来源: https://www.cnblogs.com/CTing/p/16076577.html