一定要多取膜!不然一直卡60分!
在区间中进行更新于查询,很好想到用线段树
为了增加速度,我们可以用到lazy标记,不过这题有乘法,我们需要修改一下
定义结构体:
struct SegmentTree
{
long long l,r;
long long sum;
long long addmark=0,mulmark=1;//加法的标记和乘法的标记
}t[400010];//四倍开点
乘法更新:
if(x<=l&&y>=r)
{
t[id].sum=v%p*t[id].sum%p;
t[id].mulmark=t[id].mulmark*v%p;//乘标要乘上去
t[id].addmark=t[id].addmark*v%p;//加标也要乘(想一想为什么?)
return;
}
加法更新
if(x<=l&&y>=r)
{
t[id].sum=(t[id].sum+v%p*(r-l+1)%p)%p;//这个不用解释吧
t[id].addmark=(t[id].addmark+v%p)%p;
return;
}
下传标记
void PushDown(long long id)
{
t[id*2].mulmark=t[id].mulmark%p*t[id*2].mulmark%p;//乘标是乘上去的
t[id*2+1].mulmark=t[id].mulmark%p*t[id*2+1].mulmark%p;
t[id*2].addmark=(t[id*2].addmark%p*t[id].mulmark%p+t[id].addmark)%p;//加标要乘上下传下来的乘标
t[id*2+1].addmark=(t[id*2+1].addmark%p*t[id].mulmark%p+t[id].addmark)%p;
t[id*2].sum=(t[id].mulmark%p*t[id*2].sum%p+t[id].addmark*(t[id*2].r-t[id*2].l+1)%p)%p;//先乘后加
t[id*2+1].sum=(t[id].mulmark%p*t[id*2+1].sum%p+t[id].addmark*(t[id*2+1].r-t[id*2+1].l+1)%p)%p;
t[id].addmark=0;//记得清0
t[id].mulmark=1;
}
贴完整代码
#include<bits/stdc++.h>
#define lson id*2,l,mid
#define rson id*2+1,mid+1,r
using namespace std;
long long n,m,p;
struct SegmentTree
{
long long l,r;
long long sum;
long long addmark=0,mulmark=1;
}t[400010];
void BuildTree(long long,long long,long long);
void Update1(long long,long long,long long,long long,long long,long long);
void Update2(long long,long long,long long,long long,long long,long long);
long long Query(long long,long long,long long,long long,long long);
void PushDown(long long);
int main()
{
scanf("%lld%lld",&n,&p);
BuildTree(1,1,n);
scanf("%lld",&m);
for(long long i=1;i<=m;i++)
{
long long k;
scanf("%lld",&k);
if(k==1)
{
long long x,y,o;
scanf("%lld%lld%lld",&x,&y,&o);
Update1(1,1,n,x,y,o);
}
if(k==2)
{
long long x,y,o;
scanf("%lld%lld%lld",&x,&y,&o);
Update2(1,1,n,x,y,o);
}
if(k==3)
{
long long x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",Query(1,1,n,x,y)%p);
}
}
return 0;
}
void BuildTree(long long id,long long l,long long r)
{
t[id].l=l;
t[id].r=r;
if(l==r)
{
scanf("%lld",&t[id].sum);
return;
}
long long mid=(l+r)>>1;
BuildTree(lson);
BuildTree(rson);
t[id].sum=(t[id*2].sum+t[id*2+1].sum)%p;
}
void Update1(long long id,long long l,long long r,long long x,long long y,long long v)
{
long long mid=(l+r)>>1;
if(x<=l&&y>=r)
{
t[id].sum=v%p*t[id].sum%p;
t[id].mulmark=t[id].mulmark*v%p;
t[id].addmark=t[id].addmark*v%p;
return;
}
PushDown(id);
if(x<=mid)Update1(id*2,l,mid,x,y,v);
if(y>mid)Update1(id*2+1,mid+1,r,x,y,v);
t[id].sum=(t[id*2].sum+t[id*2+1].sum)%p;
}
void Update2(long long id,long long l,long long r,long long x,long long y,long long v)
{
long long mid=(l+r)>>1;
if(x<=l&&y>=r)
{
t[id].sum=(t[id].sum+v%p*(r-l+1)%p)%p;
t[id].addmark=(t[id].addmark+v%p)%p;
return;
}
PushDown(id);
if(x<=mid)Update2(id*2,l,mid,x,y,v);
if(y>mid)Update2(id*2+1,mid+1,r,x,y,v);
t[id].sum=(t[id*2].sum+t[id*2+1].sum)%p;
}
long long Query(long long id,long long l,long long r,long long x,long long y)
{
long long mid=(l+r)>>1;
long long sum=0;
if(x<=l&&y>=r)return t[id].sum;
PushDown(id);
if(x<=mid)sum=(sum+Query(id*2,l,mid,x,y))%p;
if(y>mid)sum=(sum+Query(id*2+1,mid+1,r,x,y))%p;
return sum;
}
void PushDown(long long id)
{
t[id*2].mulmark=t[id].mulmark%p*t[id*2].mulmark%p;
t[id*2+1].mulmark=t[id].mulmark%p*t[id*2+1].mulmark%p;
t[id*2].addmark=(t[id*2].addmark%p*t[id].mulmark%p+t[id].addmark)%p;
t[id*2+1].addmark=(t[id*2+1].addmark%p*t[id].mulmark%p+t[id].addmark)%p;
t[id*2].sum=(t[id].mulmark%p*t[id*2].sum%p+t[id].addmark*(t[id*2].r-t[id*2].l+1)%p)%p;
t[id*2+1].sum=(t[id].mulmark%p*t[id*2+1].sum%p+t[id].addmark*(t[id*2+1].r-t[id*2+1].l+1)%p)%p;
t[id].addmark=0;
t[id].mulmark=1;
}