lazytag 包括加和乘 所以需要两个数组分别标记,并且最最重要的一点 乘法会连带着把加法用的数组连带着修改掉,加法只会修改自己的lazy数组
#include <bits/stdc++.h>
#define int long long
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mid (L+R>>1)
using namespace std;
const int N = 1e5+10;
int sum[N<<4],lazy1[N<<4],lazy2[N<<4];
int a[N];
int n,m,p;
void add(int v,int L,int R,int rt)
{
lazy1[rt] = (lazy1[rt]+v%p)%p;
sum[rt] = (sum[rt] + (R-L+1)*v%p) %p;
}
void mul(int v,int L,int R,int rt)
{
lazy2[rt] = (lazy2[rt]*v)%p;
lazy1[rt] = (lazy1[rt]*v)%p;
sum[rt] = (sum[rt]*v)%p;
}
void pushdown(int m,int L,int R,int rt)
{
if(lazy2[rt] != 1)
{
mul(lazy2[rt],L,m,lson);
mul(lazy2[rt],m+1,R,rson);
lazy2[rt] = 1;
}
if(lazy1[rt] != 0)
{
add(lazy1[rt],L,m,lson);
add(lazy1[rt],m+1,R,rson);
lazy1[rt] = 0;
}
}
void build(int L = 1,int R = n,int rt = 1)
{
sum[rt] = 0; lazy1[rt] = 0; lazy2[rt] = 1;
if(L==R)
{
sum[rt] = a[L];return;
}
build(L,mid,lson); build(mid+1,R,rson);
sum[rt] = (sum[lson] + sum[rson]) % p;
}
void update(int l,int r,int v,int op,int L = 1,int R = n,int rt = 1)
{
if(l <= L && R <= r)
{
if(op == 1) mul(v,L,R,rt);
else add(v,L,R,rt);
return;
}
pushdown(mid,L,R,rt);
if(l <= mid) update(l,r,v,op,L,mid,lson);
if(r > mid) update(l,r,v,op,mid+1,R,rson);
sum[rt] = (sum[lson] + sum[rson])%p;
}
int query(int l,int r,int L = 1,int R = n,int rt = 1)
{
if(l <= L && R <= r) return sum[rt];
pushdown(mid,L,R,rt);
int ans = 0;
if(l <= mid) ans = (ans + query(l,r,L,mid,lson)) %p;
if(r > mid) ans = (ans + query(l,r,mid+1,R,rson)) %p;
return ans%p;
}
signed main()
{
cin >> n >> p;
for(int i = 1; i <= n; ++i) scanf("%lld",&a[i]);
build();
cin >> m;
while(m--)
{
int op,a,b,v; cin >> op >> a >> b;
if(op != 3)
{
cin >> v; update(a,b,v,op);
}
else cout << query(a,b) << "\n";
}
}