以洛谷P3372为例
#include<cstdio>
#include<cstring>
#define lc (o<<1)
#define rc (o<<1|1)
#define mid (l+r>>1)
typedef long long ll;
const int N=1e5+5;
ll a[N],sum[N*4],lazy[N*4];//节点,和,懒操作
void push_up(int o){//维护节点信息
sum[o]=sum[lc]+sum[rc];
}
void push_down(ll o,ll l,ll r)//延迟下放
{//o节点下标,[l,r]节点范围
if(!lazy[o])return;
sum[lc]+=(mid-l+1)*lazy[o];
lazy[lc]+=lazy[o];
sum[rc]+=(r-mid)*lazy[o];
lazy[rc]+=lazy[o];
lazy[o]=0;
}
void jianshu(ll o,ll l,ll r)//建树
{//o节点下标,[l,r]节点范围
lazy[o]=0;
if(l==r)
{//叶子节点
sum[o]=a[l];
return;
}
jianshu(lc,l,mid);jianshu(rc,mid+1,r);
push_up(o);//维护子节点
}
void update(ll o,ll l,ll r,ll nl,ll nr,ll v)
{//o节点下标,[l,r]节点范围,[nl,nr]修改范围,v修改数值
if(l==nl&&r==nr)
{//刚好
sum[o]+=(r-l+1)*v;
lazy[o]+=v;
return;
}
push_down(o,l,r);//延迟下放
if(nr<=mid)//全在左
update(lc,l,mid,nl,nr,v);
else if(nl>mid)//全在右
update(rc,mid+1,r,nl,nr,v);
else
{//分两边
update(lc,l,mid,nl,mid,v);
update(rc,mid+1,r,mid+1,nr,v);
}
push_up(o);//维护子节点
}
ll query(ll o,ll l,ll r,ll nl,ll nr)
{//o节点下标,[l,r]节点范围,[nl,nr]查询范围
if(l==nl&&r==nr)//刚好
return sum[o];
push_down(o,l,r);//延迟下放
if(nr<=mid)//全在左
return query(lc,l,mid,nl,nr);
else if(nl>mid)//全在右
return query(rc,mid+1,r,nl,nr);
//分两边
return query(lc,l,mid,nl,mid)+query(rc,mid+1,r,mid+1,nr);
}
int main()
{
//freopen("in.txt","r",stdin);
memset(a,0,sizeof(a));
ll n,m,i,c,x,y,k;
scanf("%lld%lld",&n,&m);
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
jianshu(1,1,n);
for(i=1;i<=m;i++)
{
scanf("%lld",&c);
if(c==2)
{
scanf("%lld%lld",&x,&y);//多打一个%
printf("%lld\n",query(1,1,n,x,y));
}
else if(c==1)
{
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k);
}
}
return 0;
}
以洛谷P3373为例
#include<cstdio>
#include<cstring>
#define lc (o<<1)
#define rc (o<<1|1)
#define mid (l+r>>1)
typedef long long ll;
ll n,m,p;
const int N=1e5+5;
ll a[N],sum[N<<2],add[N<<2],mul[N<<2];
inline void push_up(ll o)
{
sum[o]=(sum[lc]+sum[rc])%p;
return;
}
inline void push_down(ll o,ll l,ll r)
{
if(mul[o]!=1)
{
sum[lc]=sum[lc]*mul[o]%p;
sum[rc]=sum[rc]*mul[o]%p;
mul[lc]=mul[lc]*mul[o]%p;
mul[rc]=mul[rc]*mul[o]%p;
add[lc]=add[lc]*mul[o]%p;
add[rc]=add[rc]*mul[o]%p;
mul[o]=1;
}
if(add[o])
{
sum[lc]+=add[o]*(mid-l+1)%p;
if(sum[lc]>=p)sum[lc]-=p;
sum[rc]+=add[o]*(r-mid)%p;
if(sum[rc]>=p)sum[rc]-=p;
add[lc]+=add[o];
if(add[lc]>=p)add[lc]-=p;
add[rc]+=add[o];
if(add[rc]>=p)add[rc]-=p;
add[o]=0;
}
}
void build(ll o,ll l,ll r)
{
mul[o]=1;add[o]=0;
if(l==r)
{
sum[o]=a[l];
return;
}
build(lc,l,mid);build(rc,mid+1,r);
push_up(o);
}
void update_mul(ll o,ll l,ll r,ll nl,ll nr,ll v)
{
if(nl==l&&r==nr)
{
sum[o]=sum[o]*v%p;
mul[o]=mul[o]*v%p;
add[o]=add[o]*v%p;
return;
}
push_down(o,l,r);
if(nr<=mid)update_mul(lc,l,mid,nl,nr,v);
else if(nl>mid)update_mul(rc,mid+1,r,nl,nr,v);
else update_mul(lc,l,mid,nl,mid,v),update_mul(rc,mid+1,r,mid+1,nr,v);
push_up(o);
}
void update_add(ll o,ll l,ll r,ll nl,ll nr,ll v)
{
if(nl==l&&r==nr)
{
sum[o]+=(r-l+1)*v%p;
if(sum[o]>=p)sum[o]-=p;
add[o]+=v;
if(add[o]>=p)add[o]-=p;
return;
}
push_down(o,l,r);
if(nr<=mid)update_add(lc,l,mid,nl,nr,v);
else if(nl>mid)update_add(rc,mid+1,r,nl,nr,v);
else update_add(lc,l,mid,nl,mid,v),update_add(rc,mid+1,r,mid+1,nr,v);
push_up(o);
}
ll query(ll o,ll l,ll r,ll nl,ll nr)
{
if(nl==l&&r==nr)return sum[o];
push_down(o,l,r);
if(nr<=mid)return query(lc,l,mid,nl,nr);
else if(nl>mid)return query(rc,mid+1,r,nl,nr);
else return query(lc,l,mid,nl,mid)%p+query(rc,mid+1,r,mid+1,nr)%p;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%lld%lld%lld",&n,&m,&p);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
ll op,x,y,k;
for(ll i=1;i<=m;i++)
{
scanf("%lld",&op);
if(op==1)
{
scanf("%lld%lld%lld",&x,&y,&k);
update_mul(1,1,n,x,y,k);
}
else if(op==2)
{
scanf("%lld%lld%lld",&x,&y,&k);
update_add(1,1,n,x,y,k);
}
else if(op==3)
{
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(1,1,n,x,y)%p);
}
}
return 0;
}