1.区间上每一个点的值乘一个数
2.区间上每一个点的值加一个数
3.查询一段区间的数值之和
线段树裸题
注意:传乘法标记的时候,初始值要设成1
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N=100005;
struct SegMentTree
{ll l,r,mul,plu,sum;}T[N*4];
ll mod,n,m,a[N];
void build(ll x,ll l,ll r)
{
T[x].l=l,T[x].r=r;
if(l==r)
{
T[x].sum=a[l]%mod;
return;
}
ll mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
T[x].sum=(T[x<<1].sum+T[x<<1|1].sum)%mod;
}
void pushdown(ll x)
{
ll lc=x<<1,rc=x<<1|1;
ll ls=T[lc].r-T[lc].l+1,rs=T[rc].r-T[rc].l+1;
T[lc].sum=(T[lc].sum*T[x].mul)%mod,T[rc].sum=(T[rc].sum*T[x].mul)%mod;
T[lc].sum=(T[lc].sum+T[x].plu*ls)%mod,T[rc].sum=(T[rc].sum+T[x].plu*rs)%mod;
if(T[x].mul!=1)
{
T[lc].mul=T[lc].mul*T[x].mul%mod;
T[lc].plu=T[lc].plu*T[x].mul%mod;
T[rc].mul=T[rc].mul*T[x].mul%mod;
T[rc].plu=T[rc].plu*T[x].mul%mod;
}
if(T[x].plu)
{
T[lc].plu=(T[lc].plu+T[x].plu)%mod;
T[rc].plu=(T[rc].plu+T[x].plu)%mod;
}
T[x].mul=1;
T[x].plu=0;
}
void Modify(ll x,ll l,ll r,ll c,ll flag)
{
if(T[x].l==l&&T[x].r==r)
{
ll len=T[x].r-T[x].l+1,lc=x<<1,rc=x<<1|1;
if(flag==1)
{
T[x].sum=c*T[x].sum%mod;
T[x].mul=T[x].mul*c%mod;
T[x].plu=T[x].plu*c%mod;
}
if(flag==2)
{
T[x].sum=(T[x].sum+c*len)%mod;
T[x].plu=(T[x].plu+c)%mod;
}
return;
}
if(T[x].mul!=1||T[x].plu) pushdown(x);
ll mid=(T[x].l+T[x].r)>>1;
if(r<=mid) Modify(x<<1,l,r,c,flag);
else if(l>mid) Modify(x<<1|1,l,r,c,flag);
else Modify(x<<1,l,mid,c,flag),Modify(x<<1|1,mid+1,r,c,flag);
T[x].sum=(T[x<<1].sum+T[x<<1|1].sum)%mod;
}
ll Query(ll x,ll l,ll r)
{
if(T[x].l==l&&T[x].r==r) return T[x].sum%mod;
if(T[x].mul!=1||T[x].plu) pushdown(x);
ll mid=(T[x].l+T[x].r)>>1;
if(r<=mid) return Query(x<<1,l,r);
else if(l>mid) return Query(x<<1|1,l,r);
else return (Query(x<<1,l,mid)+Query(x<<1|1,mid+1,r))%mod;
}
int main()
{
scanf("%lld%lld",&n,&mod);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
<span style="white-space:pre"> </span>for(int i=1;i<=n*4;i++) T[i].mul=1;
build(1,1,n);
scanf("%lld",&m);
ll o,l,r,c;
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&o,&l,&r);
if(o==3) printf("%lld\n",Query(1,l,r));
else
{
scanf("%lld",&c);
Modify(1,l,r,c%mod,o);
}
}
}