P3373 【模板】线段树 2
考虑到有乘法和加法,因此要考虑一个优先的,考虑乘法优先,子节点的懒标记mul更新为mulm而add为addm+a。
点击查看代码
#include <iostream>
#include <stack>
#include <cmath>
#include <algorithm>
#include <set>
#include <vector>
#include <climits>
#include <string.h>
#include <map>
#include <queue>
#include <list>
#include <cmath>
#include <iomanip>
#define int long long
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define lc u<<1
#define rc u<<1|1
#define gcd __gcd
#define double long double
#define endl "\n"
#define INF LLONG_MAX
#define mod 1000000007
#define N 100005
const double PI = 3.14159265358979323846;
using namespace std;
struct Node {int l, r, sum, mul, add;}tr[N*4];
int n, p, q,a[N];
void pushup(int u) { tr[u].sum = (tr[lc].sum + tr[rc].sum)%p; }
void calc(Node &t, int m, int a)//先乘后加
{
t.sum = (t.sum * m + (t.r - t.l + 1) * a) % p;
t.mul = t.mul * m % p;
t.add = (t.add * m + a) % p;
}
void pushdown(int u)//懒标记下传
{
calc(tr[lc], tr[u].mul, tr[u].add);
calc(tr[rc], tr[u].mul, tr[u].add);
tr[u].add = 0; tr[u].mul = 1;
}
void build(int u, int l, int r)
{
tr[u] = { l,r,a[l],1,0 };
if (l == r)return;
int mid = l + r >> 1;
build(lc, l, mid); build(rc, mid + 1, r);
pushup(u);
}
void change(int u, int l, int r, int m, int a)
{
if (l > tr[u].r || r < tr[u].l)return;
if (l <= tr[u].l && tr[u].r <= r)
{
calc(tr[u], m, a);//加了懒标记
return;
}
pushdown(u);
change(lc, l, r, m, a); change(rc, l, r, m, a);
pushup(u);
}
int query(int u, int l, int r)
{
if (l > tr[u].r || r < tr[u].l) return 0;
if (l <= tr[u].l && r >= tr[u].r)return tr[u].sum;
pushdown(u);
return (query(lc, l, r) + query(rc, l , r)) % p;//查询
}
signed main()
{
ios;//会超时
cin >> n >> q >> p;
for (int i = 1; i <= n; i++)cin >> a[i];
build(1, 1, n);
while (q--)
{
int op; cin >> op;
if (op == 1)
{
int x, y, k; cin >> x >> y >> k;
change(1, x, y, k,0);
}
else if (op == 2)
{
int x, y, k; cin >> x >> y >> k;
change(1, x, y, 1,k);
}
else
{
int x, y; cin >> x >> y;
cout << query(1, x, y) << endl;
}
}
}

浙公网安备 33010602011771号