传送门
这道题属实是线段树的道比刷题,又加又乘的,当然还可能会有乘除,阶乘等等可能的情况。
对于这道题,主要的一个就是怎么记录lazy标记,首先的话一个数组是肯定不行的,设乘的为lazy,加的为add。
每次我们更新时,要用lazy数组去更新add数组。
关键是pushdown的时候注意一下,下放的时候比较复杂。
代码如下:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define inff 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define me(a,b) memset(a,b,sizeof(a))
#define min4(a,b,c,d) min(min(a,b),min(c,d))
#define min3(x,y,z) min(min(x,y),min(y,z))
#define max4(a,b,c,d) max(max(a,b),max(c,d))
#define max3(x,y,z) max(max(x,y),max(y,z))
typedef long long ll;
using namespace std;
const int maxn=1e5+5;
ll mod,n,m;
ll tree[maxn<<2],lazy[maxn<<2],add[maxn<<2],a[maxn];
void pushup(int i,int l,int r)
{
tree[i]=(tree[lson]+tree[rson])%mod;
}
///i表示父亲,lson左儿子,rson右儿子,lazy记录乘,add记录加
void pushdown(int i,int l,int r)
{
if(lazy[i]==1&&add[i]==0)//如果乘的为1,加的为0,就不做处理
return;
int mid=half;
lazy[lson]=lazy[i]*lazy[lson]%mod;
add[lson]=(lazy[i]*add[lson]%mod+add[i])%mod;
tree[lson]=(lazy[i]*tree[lson]%mod+add[i]*(mid-l+1)%mod)%mod;
lazy[rson]=lazy[rson]*lazy[i]%mod;
add[rson]=(lazy[i]*add[rson]%mod+add[i])%mod;
tree[rson]=(lazy[i]*tree[rson]%mod+add[i]*(r-mid)%mod)%mod;
lazy[i]=1;
add[i]=0;
}
void update(int i,int l,int r,ll ql,ll qr,ll val,ll x)
{
if(ql<=l&&qr>=r)
{
if(x==1)
{
lazy[i]=lazy[i]*val%mod;
add[i]=add[i]*val%mod;
tree[i]=tree[i]*val%mod;
}
else
{
add[i]=(add[i]+val)%mod;
tree[i]=(tree[i]+(r-l+1)*val)%mod;
}
return;
}
pushdown(myself);
int mid=half;
if(qr<=mid) update(Lson,ql,qr,val,x);
else if(ql>mid) update(Rson,ql,qr,val,x);
else
{
update(Lson,ql,mid,val,x);
update(Rson,mid+1,qr,val,x);
}
pushup(myself);
}
ll query(int i,int l,int r,ll ql,ll qr)
{
if(ql<=l&&qr>=r)
return tree[i]%mod;
pushdown(myself);
int mid=half;
ll ans=0;
if(ql<=mid) ans=(ans+query(Lson,ql,qr))%mod;
if(qr>mid) ans=(ans+query(Rson,ql,qr))%mod;
return ans;
}
void build(int i,int l,int r)
{
lazy[i]=1;
add[i]=0;
if(l==r)
{
tree[i]=a[l];
return ;
}
int mid=half;
build(Lson);
build(Rson);
pushup(myself);
}
int main()
{
while(scanf("%lld %lld",&n,&mod)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
a[i]%=mod;
}
build(1,1,n);
scanf("%lld",&m);
ll num,x,y,z;
while(m--)
{
scanf("%lld",&num);
if(num!=3)
{
scanf("%lld %lld %lld",&x,&y,&z);
update(1,1,n,x,y,z,num);
}
else
{
scanf("%lld %lld",&x,&y);
printf("%lld\n",query(1,1,n,x,y)%mod);
}
}
}
return 0;
}