题解 P3373 【【模板】线段树 2】
我来发一个C++题解吧,
也是受了p党题解的启发,用了两个lazy标记各存加法和乘法结果
大家可能觉得pushdown()部分过于冗长,但是事实上%p为了防炸,而且lazy1,lazy2更新时,都需要调用爸爸节点的lazy1,lazy2,所以不能写成单独的加法更新和乘法更新,不然会WA(不要问我怎么知道的)。
然而建议把加法修改和乘法修改分开写以提高效率。
最后一条——
_不要试图提交本题解所提供的代码,除非您是玄学大佬(误),否则极有可能会T掉最后三个点(不要问我怎么知道的)_
//%std
#include<bits/stdc++.h>
using namespace std;
int n,m,p;
long long a[500200],f[500200];
struct tree
{
long long l,r,sum,lazy1,lazy2;
} t[500200];
void buildtree(int l,int r,int i)
{
int zuo=i<<1;
t[i].l=l;
t[i].r=r;
t[i].lazy1=0;
t[i].lazy2=1;
if(l==r)
t[i].sum=a[l];
else
{
int mid=(l+r)>>1;
buildtree(l,mid,zuo);
buildtree(mid+1,r,zuo|1);
t[i].sum=t[zuo].sum+t[zuo|1].sum;
}
return;
}
void pushdown(int i)
{
int zuo=i<<1;
if(t[i].lazy1==0&&t[i].lazy2==1) return;
if(t[i].l==t[i].r)
{
t[i].lazy2=1;
t[i].lazy1=0;
return;
}
t[zuo].sum=(t[zuo].sum*t[i].lazy2+t[i].lazy1*(t[zuo].r-t[zuo].l+1))%p;
t[zuo|1].sum=(t[zuo|1].sum*t[i].lazy2+t[i].lazy1*(t[zuo|1].r-t[zuo|1].l+1))%p;
t[zuo].lazy2=t[zuo].lazy2*t[i].lazy2%p;
t[zuo].lazy1=(t[zuo].lazy1*t[i].lazy2+t[i].lazy1)%p;
t[zuo|1].lazy2=t[zuo|1].lazy2*t[i].lazy2%p;
t[zuo|1].lazy1=(t[zuo|1].lazy1*t[i].lazy2+t[i].lazy1)%p;
t[i].lazy2=1;
t[i].lazy1=0;
return;
}
void xiu_1(int i,int l,int r,long long add)
{
pushdown(i);
int zuo=i<<1;
if(l<=t[i].l&&r>=t[i].r)
{
t[i].sum+=(t[i].r-t[i].l+1)*add%p;
t[i].lazy1=add%p;
return;
}
if(l>t[i].r||r<t[i].l)
return;
xiu_1(zuo,l,r,add);
xiu_1(zuo|1,l,r,add);
t[i].sum=(t[zuo].sum+t[zuo|1].sum)%p;
return;
}
void xiu_2(int i,int l,int r,long long add)
{
int zuo=i<<1;
pushdown(i);
if(l<=t[i].l&&r>=t[i].r)
{
t[i].sum=t[i].sum*add%p;
t[i].lazy2=add%p;
return;
}
if(l>t[i].r||r<t[i].l)
return;
xiu_2(zuo,l,r,add);
xiu_2(zuo|1,l,r,add);
t[i].sum=(t[zuo].sum+t[zuo|1].sum)%p;
return;
}
long long query(int i,int l,int r)
{
int zuo=i<<1;
if(l<=t[i].l&&r>=t[i].r)
return t[i].sum;
if(l>t[i].r||r<t[i].l)
return 0;
pushdown(i);
return query(zuo,l,r)+query(zuo|1,l,r);
}
long long lread()
{
long long f=1,n=0;
char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-')
f=-1;
c=getchar();
}
while(c<='9'&&c>='0')
{
n*=10;
n+=c-'0';
c=getchar();
}
return n*f;
}
int read()
{
int f=1,n=0;
char c=getchar();
while(c>'9'||c<'0')
{
if(c=='-')
f=-1;
c=getchar();
}
while(c<='9'&&c>='0')
{
n*=10;
n+=c-'0';
c=getchar();
}
return n*f;
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=1; i<=n; i++)
a[i]=lread();
buildtree(1,n,1);
for(int i=1; i<=m; i++)
{
int key;
scanf("%d",&key);
if(key==1)
{
int x=read(),y=read(),k=read();
xiu_2(1,x,y,k);
}
else if(key==2)
{
int x=read(),y=read(),k=read();
xiu_1(1,x,y,k);
}
else
{
int x=read(),y=read();
printf("%d\n",query(1,x,y)%p);
}
}
return 0;
}