链接:https://www.luogu.org/problemnew/show/P2023
裸的线段树维护+*
代码:
#include <bits/stdc++.h>
using namespace std;
#define maxn 400010
#define mid (h+t)/2
#define ll long long
ll n,m,a[maxn],mo,c,d,e,lazy1[maxn],lazy2[maxn];
struct re
{
ll h,t,x;
}p[maxn];
void updata(ll x)
{
p[x].x=(p[x*2].x+p[x*2+1].x)%mo;
}
void build(ll x,ll h,ll t)
{
p[x].h=h; p[x].t=t;
if (h==t)
{
p[x].x=a[h]; return;
}
build(x*2,h,mid); build(x*2+1,mid+1,t);
updata(x);
}
void down(ll x)
{
if (lazy2[x]!=1)
{
p[x].x=(p[x].x*lazy2[x])%mo;
if (p[x].h!=p[x].t) //这一句效率有明显提高
{
lazy2[x*2]=(lazy2[x*2]*lazy2[x])%mo;
lazy2[x*2+1]=(lazy2[x*2+1]*lazy2[x])%mo;
lazy1[x*2]=(lazy1[x*2]*lazy2[x])%mo;
lazy1[x*2+1]=(lazy1[x*2+1]*lazy2[x])%mo;
}}
if (lazy1[x])
{
p[x].x=(p[x].x+lazy1[x]*(p[x].t-p[x].h+1))%mo;
if (p[x].h!=p[x].t)
{
lazy1[x*2]=(lazy1[x*2]+lazy1[x])%mo;
lazy1[x*2+1]=(lazy1[x*2+1]+lazy1[x])%mo;
}}
lazy1[x]=0; lazy2[x]=1;
}
void change1(ll x,ll h,ll t,ll num)
{
down(x);
if (p[x].h>t||p[x].t<h) return;
if (h<=p[x].h&&p[x].t<=t)
{
lazy1[x]=(lazy1[x]+num)%mo;
down(x);
return;
}
change1(x*2,h,t,num); change1(x*2+1,h,t,num);
updata(x);
}
void change2(ll x,ll h,ll t,ll num)
{
down(x);
if (p[x].h>t||p[x].t<h) return;
if (h<=p[x].h&&p[x].t<=t)
{
lazy1[x]=(lazy1[x]*num)%mo;
lazy2[x]=(lazy2[x]*num)%mo;
down(x);
return;
}
change2(x*2,h,t,num); change2(x*2+1,h,t,num);
updata(x);
}
ll query(ll x,ll h,ll t)
{
down(x);
if (p[x].h>t||p[x].t<h) return(0);
if (h<=p[x].h&&p[x].t<=t) return(p[x].x);
return((query(x*2,h,t)+query(x*2+1,h,t))%mo);
}
int main()
{
std::ios::sync_with_stdio(false);
cin>>n>>m>>mo;
for (ll i=1;i<=n;i++) cin>>a[i];
for (int i=1;i<=maxn-1;i++) lazy2[i]=1;
build(1,1,n);
for (ll i=1;i<=m;i++)
{
int c,d,e,f;
cin>>c;
if (c==1)
{
cin>>d>>e>>f;
change2(1,d,e,f);
}
if (c==2)
{
cin>>d>>e>>f;
change1(1,d,e,f);
}
if (c==3)
{
cin>>d>>e;
cout<<query(1,d,e)%mo<<endl;
}
}
return 0;
}