线段树(3)——区间操作叠加
如果我既有区间乘法又有区间加法,我应该怎么办呢?
这时候需要写两个标记。假设只写一个标记。
标记加法:此时对于乘法操作,因为是将
标记乘法:那我加法咋办?
那两个标记怎么用呢?首先假设加法标记为
首先考虑
以下代码参考题目:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,p,m,a[N],t[N*8],lazy[N*8],multi[N*8];
void push_down_add(int now,int tl,int tr){
int mid=(tl+tr)/2;
t[now*2]=(t[now*2]+lazy[now]*(mid-tl+1))%p;
t[now*2+1]=(t[now*2+1]+lazy[now]*(tr-mid))%p;
lazy[now*2]=(lazy[now*2]+lazy[now])%p;
lazy[now*2+1]=(lazy[now*2+1]+lazy[now])%p;
lazy[now]=0;
}
void push_down_multi(int now,int tl,int tr){
int mid=(tl+tr)/2;
t[now*2]=t[now*2]*multi[now]%p;
t[now*2+1]=t[now*2+1]*multi[now]%p;
multi[now*2]=multi[now*2]*multi[now]%p;
multi[now*2+1]=multi[now*2+1]*multi[now]%p;
lazy[now*2]=lazy[now*2]*multi[now]%p;
lazy[now*2+1]=lazy[now*2+1]*multi[now]%p;
multi[now]=1;
}
void build(int now,int tl,int tr){
multi[now]=1;
if(tl==tr){
t[now]=a[tl];
return ;
}
int mid=(tl+tr)/2;
build(now*2,tl,mid);
build(now*2+1,mid+1,tr);
t[now]=(t[now*2]+t[now*2+1])%p;
}
void modify_add(int now,int tl,int tr,int l,int r,int x){
if(tl>=l&&tr<=r){
t[now]=(t[now]+x*(tr-tl+1))%p;
lazy[now]=(lazy[now]+x)%p;
return ;
}
if(tl>r||tr<l){
return ;
}
if(multi[now]!=1){
push_down_multi(now,tl,tr);
}
if(lazy[now]){
push_down_add(now,tl,tr);
}
int mid=(tl+tr)/2;
modify_add(now*2,tl,mid,l,r,x);
modify_add(now*2+1,mid+1,tr,l,r,x);
t[now]=(t[now*2]+t[now*2+1])%p;
}
void modify_multi(int now,int tl,int tr,int l,int r,int x){
if(tl>=l&&tr<=r){
t[now]=t[now]*x%p;
multi[now]=multi[now]*x%p;
lazy[now]=lazy[now]*x%p;
return ;
}
if(tl>r||tr<l){
return ;
}
if(multi[now]!=1){
push_down_multi(now,tl,tr);
}
if(lazy[now]){
push_down_add(now,tl,tr);
}
int mid=(tl+tr)/2;
modify_multi(now*2,tl,mid,l,r,x);
modify_multi(now*2+1,mid+1,tr,l,r,x);
t[now]=(t[now*2]+t[now*2+1])%p;
}
int query(int now,int tl,int tr,int l,int r){
if(tl>=l&&tr<=r){
return t[now];
}
if(tl>r||tr<l){
return 0;
}
if(multi[now]!=1){
push_down_multi(now,tl,tr);
}
if(lazy[now]){
push_down_add(now,tl,tr);
}
int mid=(tl+tr)/2;
return (query(now*2,tl,mid,l,r)+query(now*2+1,mid+1,tr,l,r))%p;
}
signed main(){
//freopen("xx.in","r",stdin);
//freopen("xx.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
cin>>a[i];
}
build(1,1,n);
while(m--){
int opt,t,g,c;
cin>>opt;
if(opt==1){
cin>>t>>g>>c;
modify_multi(1,1,n,t,g,c);
}else if(opt==2){
cin>>t>>g>>c;
modify_add(1,1,n,t,g,c);
}else{
cin>>t>>g;
cout<<query(1,1,n,t,g)<<"\n";
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?