P3373 【模板】线段树 2 题解
解题思路
分块做法
加法乘法打上标记,然后零散块下传一下就可以了。
开 long long 后减少取模次数可以有效减少运行时间。
然后加上快读就可以稳定 AC 了。
AC 代码
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#define int long long
#define N 100005
#define M 350
void read(int &x){
x=0;bool flag(0);char ch=getchar();
while(ch<'0'||ch>'9') flag^=ch=='-',ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
flag?x=-x:0;
}
void write(int x)
{
x<0?x=-x,putchar('-'):0;static short Stack[50],top(0);
do Stack[++top]=x%10,x/=10;while(x);
while(top) putchar(Stack[top--]|48);
putchar('\n');
}
int n,q,a[N];
int Mod,pos[N];
struct Block{
int l,r;
int add;
int mul;
int sum;
int len;
Block():mul(1){}
inline void Init(){
for(register int i=l;i<=r;++i)
sum+=a[i];
sum%=Mod;
len=r-l+1;
}
inline void Add(
const int &v
){
add+=v;
sum+=v*len;
sum%=Mod;
}
inline void Mul(
const int &v
){
mul=mul*v%Mod;
sum=sum*v%Mod;
add=add*v%Mod;
}
inline void Update(){
for(register int i=l;i<=r;++i){
if(mul!=1ll)
a[i]*=mul;
a[i]%=Mod;
a[i]+=add;
}mul=1ll;sum=add=0ll;
for(register int i=l;i<=r;++i)
sum+=a[i];
sum%=Mod;
}
}block[M];
inline void Add(
const int &l,
const int &r,
const int &v
){
register int x=pos[l];
register int y=pos[r];
if(x==y){
block[x].Update();
for(register int i=l;i<=r;++i)
a[i]+=v;
block[x].Update();
return;
}
block[x].Update();
for(register int i=l;i<=block[x].r;++i)
a[i]+=v;
block[x].Update();
block[y].Update();
for(register int i=block[y].l;i<=r;++i)
a[i]+=v;
block[y].Update();
for(register int i=x+1;i<y;++i)
block[i].Add(v);
}
inline void Mul(
const int &l,
const int &r,
const int &v
){
register int x=pos[l];
register int y=pos[r];
if(x==y){
block[x].Update();
for(register int i=l;i<=r;++i)
a[i]=a[i]*v;
block[x].Update();
return;
}
block[x].Update();
for(register int i=l;i<=block[x].r;++i)
a[i]=a[i]*v;
block[x].Update();
block[y].Update();
for(register int i=block[y].l;i<=r;++i)
a[i]=a[i]*v;
block[y].Update();
for(register int i=x+1;i<y;++i)
block[i].Mul(v);
}
inline void Query(
const int &l,
const int &r
){
register int x=pos[l];
register int y=pos[r];
if(x==y){
register int res=0;
block[x].Update();
for(register int i=l;i<=r;++i)
res+=a[i];
write(res%Mod);
return;
}
register int res=0;
block[x].Update();
for(register int i=l;i<=block[x].r;++i)
res+=a[i];
block[y].Update();
for(register int i=block[y].l;i<=r;++i)
res+=a[i];
for(register int i=x+1;i<y;++i)
res+=block[i].sum;
write(res%Mod);
}
signed main(){
read(n),read(q);read(Mod);
for(register int i=1;i<=n;++i)
read(a[i]);
int t=sqrt(n+1);
for(register int i=1;i<=t;++i){
block[i].r=i*t;
block[i].l=(i-1)*t+1;
}
if(block[t].r<n){
++t;block[t].r=n;
block[t].l=block[t-1].r+1;
}
for(register int i=1;i<=t;++i)
for(
register int j=block[i].l;
j<=block[i].r;++j
) pos[j]=i;
for(register int i=1;i<=t;++i)
block[i].Init();
int opt,l,r,x;
while(q--){
read(opt);
read(l),read(r);
if(opt<3) read(x);
switch (opt){
case 1:Mul(l,r,x);break;
case 2:Add(l,r,x);break;
case 3:Query(l,r);break;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下