题目链接:P3373 【模板】线段树 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

这道题目的意思很明确,就是要我们在线完成区间的乘和加运算并支持查询区间和的一个问题。处理这道题目之前一定要对线段树有一定的了解,如果对线段树还不理解的小伙伴可以看下我之前的博客,在这我附上地址:(17条消息) 线段树模板_AC__dream的博客-CSDN博客

现在来对这道题目做出分析,我们知道涉及到线段树区间修改问题必然会使用懒标记,知道了线段树区间加法的小伙伴肯定会自然而然地想到使用加法懒标记和乘法懒标记来解决这道题目,但是需要注意的是加法懒标记和乘法懒标记并不是独立向下传送的,举个例子,为了便于大家理解,我就拿一个长度为1初始值也为1的区间来举例吧,我们先乘5再加10再乘6再乘7再加6再乘3,这样我们就应该得到这个区间的值为((( 1 * 5 )+ 10 )* 6 * 7 + 6 )* 3 = 1908,但如果我们把加法标记和乘法标记两个标记单独来看就应该得到乘法标记是630,加法标记是16,这样最后结果无论如何也算不对了,那问题到底出在哪了呢?我们注意到乘法标记会对加法标记产生一定的影响,先看乘5再加10再乘6这步操作,我们会发现( 1 * 5 )+ 10 )* 6=1*5*6+10*6=1*5*6+60,我们注意到加法标记应该变为60,也就是说每出现一次乘法操作都会对之前已有的加法标记产生一定的影响,我们知道了这个再看原来的操作就容易发现

((( 1 * 5 )+ 10 )* 6 * 7 + 6 )* 3=1*5*6*7*3+10*6*7*3+6*3,就是每一个乘法操作出现时,在他之前出现的加法操作就要对应地乘上相应的倍数,这也就是本道题目的难点所在了,其他就是基本的线段树模板了,下面上代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=5e5+10;
long long sum[N],sumlazy[N],mullazy[N],l[N],r[N],a[N];
int mod;
void pushup(int id)
{sum[id]=(sum[id<<1]+sum[id<<1|1])%mod;
}
void pushdown(int id)
{if(mullazy[id]!=1){//父区间的乘法标记会对子区间的加法标记产生影响sumlazy[id<<1]=sumlazy[id<<1]*mullazy[id]%mod;sumlazy[id<<1|1]=sumlazy[id<<1|1]*mullazy[id]%mod;sum[id<<1]=(sum[id<<1]*mullazy[id])%mod;sum[id<<1|1]=(sum[id<<1|1]*mullazy[id])%mod;mullazy[id<<1]=(mullazy[id<<1]*mullazy[id])%mod;mullazy[id<<1|1]=(mullazy[id<<1|1]*mullazy[id])%mod;mullazy[id]=1;}if(sumlazy[id]){sumlazy[id<<1]+=sumlazy[id];sumlazy[id<<1|1]+=sumlazy[id];sum[id<<1]=(sum[id<<1]+(r[id<<1]-l[id<<1]+1)*sumlazy[id])%mod;sum[id<<1|1]=(sum[id<<1|1]+(r[id<<1|1]-l[id<<1|1]+1)*sumlazy[id])%mod;sumlazy[id]=0;}
}
void build(int id,int L,int R)
{sum[id]=0;l[id]=L;r[id]=R;sumlazy[id]=0;mullazy[id]=1;if(L==R){sum[id]=a[L];return ;}int mid=L+R>>1;build(id<<1,L,mid);build(id<<1|1,mid+1,R);pushup(id);
}
void sumupdate_interval(int id,int L,int R,int val)
{if(l[id]>R||r[id]<L) return ;if(l[id]>=L&&r[id]<=R){sumlazy[id]+=val;sum[id]=(sum[id]+(r[id]-l[id]+1)*val)%mod;return ;}pushdown(id);sumupdate_interval(id<<1,L,R,val);sumupdate_interval(id<<1|1,L,R,val);pushup(id);
}
void mulupdate_interval(int id,int L,int R,int val)
{if(l[id]>R||r[id]<L) return ;if(l[id]>=L&&r[id]<=R){sumlazy[id]=(sumlazy[id]*val)%mod;//当前的乘法操作会影响之前已经产生加法标记 mullazy[id]=val%mod*mullazy[id]%mod;sum[id]=val%mod*sum[id]%mod;return ;}pushdown(id);mulupdate_interval(id<<1,L,R,val);mulupdate_interval(id<<1|1,L,R,val);pushup(id);
}
long long query_interval(int id,int L,int R)
{if(l[id]>R||r[id]<L) return 0;if(l[id]>=L&&r[id]<=R) return sum[id];pushdown(id);return (query_interval(id<<1,L,R)+query_interval(id<<1|1,L,R))%mod;
}
int main()
{int n,m;cin>>n>>m>>mod;int op,x,y,k;for(int i=1;i<=n;i++) scanf("%lld",&a[i]);build(1,1,n);while(m--){scanf("%d",&op);if(op==1){scanf("%d%d%d",&x,&y,&k);mulupdate_interval(1,x,y,k);}else if(op==2){scanf("%d%d%d",&x,&y,&k);sumupdate_interval(1,x,y,k);}else{scanf("%d%d",&x,&y);printf("%lld\n",query_interval(1,x,y));}}return 0;
}

洛谷(P3373)线段树加乘混合模板相关推荐

  1. 洛谷 P3373 线段树2

    洛谷 P3373 线段树2 mul和pls更新某区间左右子树sum的时候,别忘了回头更新这个区间的sum 只有在传递给子序列之后,父序列的lz标记才能清零.其他时候,lz标记只增不减 #include ...

  2. 洛谷P3373线段树

    洛谷P3373 线段树模板题,主要对懒标的处理要求比较高. 有三种操作: 区间加法 区间乘法 区间求和查询 tips:我们对一个区间进行乘k操作的时候,他之前可能存在加法lazy还没pushdown, ...

  3. 洛谷P3373 线段树2(乘法加法lazytag)

    线段树模板题,含lazytag的线段树码量本身就比较大,再加入乘法标记,还要考虑先乘后加的问题,本蒟蒻一调就是几个小时. P3373 [模板]线段树 2https://www.luogu.com.cn ...

  4. 洛谷P3373线段树2

    题目描述 区间查询区间修改,非常明显的线段树模板,但乘法和加法的结合,使问题有了些小改动: problem: 该题唯一的难点就是加法和乘法的lazytag的处理,设目前区间N.s(即区间和)=x,若先 ...

  5. 洛谷 P3373 线段树模板题

    链接:https://www.luogu.com.cn/problem/P3373 题意:一个区间 三种操作 1 给lr范围内乘一个数 2 给lr范围内加一个数 3 询问lr范围内的和 啊这题真·做了 ...

  6. 洛谷3373 线段树模板

    题目详情:https://www.luogu.org/problemnew/show/P3373 这个线段树模板写的头疼(最后纠错发现一个long long没开差点一口血喷出来),思路就是在普通的求区 ...

  7. 洛谷 3373 线段树

    传送门 思路: 关键在于乘与加的先后计算关系,(x + y) * k = x * k + y * k,从这里可以看出来,把加法转化为乘法计算,取消了+与*先后顺序 pushdown时,即为乘法标记 * ...

  8. [WC2005]双面棋盘,洛谷P4121,线段树分治+可撤销并查集

    正题 这题主要是来练手的,因为没写过可撤销的并查集,大概就是把每一个格子看成一个点,然后格子直接的边有很多的出现区间,把这些出现区间和对应的颜色打到线段树上,然后用可撤销的并查集来维护就可以了. #i ...

  9. 洛谷 P3373 【模板】线段树 2 题解

    洛谷 P3373 [模板]线段树 2 题解 题面 题目链接:[戳这里](https://www.luogu.org/problemnew/show/P3373) 题目描述 输入输出格式 输入输出样例 ...

最新文章

  1. IT职场人生系列之十八:危险职业(上)
  2. mysql从库追主库日志_Mysql主库跑太快,从库追不上怎么做?
  3. linux安装mysql字符_Linux下MySQL的彻底卸载和安装配置字符集
  4. java面试笔试大汇总(一)
  5. Python教程:int数值类型的内置函数
  6. 思维+multiset ZOJ Monthly, July 2015 - H Twelves Monkeys
  7. 使用Asp.net mvc + Linq + mvc_scaffold_gen_setup.exe 生成一个完整的家庭帐册大管家程序 之一...
  8. Hadoop-HBASE案例分析-Hadoop学习笔记二
  9. 第7届UBBF在迪拜举办 加强网络设施建设将加速产业发展成为共识
  10. 经验总结24--捕捉异常的重要性
  11. Idea利用JSP模板设置统一路径(basePath)
  12. 润乾V4.2.5 报表开发 安装 以及授权文件
  13. monk_notebook (交际德语教程 第二版 学生用书)
  14. beetle-j2ee-application-framework框架介绍.md
  15. matlab程序的m语言,M语言GMSK程序求教
  16. H264---H.264/AVC 的各大主流编解码器JM、x264、Xvid、T264、ffmpeg、ffdshow + JMHM源码分析
  17. 加密流量分类任务的深度学习方法(一般框架总结)
  18. 苹果鼠标右键怎么按_iPadOS 鼠标支持详解
  19. java上传文件的要点_Uploadify上传文件方法
  20. 博图PLC程序 停车场控制系统

热门文章

  1. rsync 是什么?
  2. Xcode 真机调试 ineligible Devices的解决方法
  3. 火车没有方向盘操纵转向,如何实现换轨?看完涨知识了
  4. 目标检测学习笔记-3D摄像头与 2D摄像头区别
  5. Kubernetes学习之路(一)之概念和架构解析和证书创建和分发
  6. 详解pandas编码函数pd.factorize()
  7. 【Android Jetpack】Room——基本使用篇
  8. 项目中引用Iconfont(阿里巴巴矢量图标)的方式
  9. 2019中国科学院、中国工程院院士增选名单正式发布
  10. 从零开始学_JavaScript_系列(五)——dojo(基础,动画移动,重力模拟,动画合并,添加标签)