链接:https://www.luogu.com.cn/problem/P3373
题意:一个区间 三种操作
1 给lr范围内乘一个数
2 给lr范围内加一个数
3 询问lr范围内的和
啊这题真·做了一上午 啊这 还是自己太菜了
因为需要两个标记 需要考虑运算顺序的问题(是先加后乘还是先乘后加)(自己也没明白 题解都说是先乘后加)
但是需要另处理加法标记
下面剖析一下代码吧
首先build函数没什么说的

void build(int k,int l,int r){t[k].l=l,t[k].r=r,t[k].lazy1=1,t[k].lazy2=0;if(l==r){t[k].sum=a[l]%mod;}else{int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);}
}

然后是pushdown函数 注意先乘后加是sum
然后注意lazy1是乘 直接乘就完了
然后注意lazy2是加 要注意lazy2也要先乘后加!!!是孩子的lazy2*父亲的lazy1 + 父亲的lazy2(先乘后加)
最后父亲俩lazy初始化。

void pushdown(int k){t[k<<1].sum*=t[k].lazy1;t[k<<1].sum%=mod;t[k<<1|1].sum*=t[k].lazy1;t[k<<1|1].sum%=mod;t[k<<1].lazy1*=t[k].lazy1;t[k<<1].lazy1%=mod;t[k<<1|1].lazy1*=t[k].lazy1;t[k<<1|1].lazy1%=mod;t[k<<1].sum+=t[k].lazy2*(t[k<<1].r-t[k<<1].l+1);t[k<<1].sum%=mod;t[k<<1|1].sum+=t[k].lazy2*(t[k<<1|1].r-t[k<<1|1].l+1);t[k<<1|1].sum%=mod;t[k<<1].lazy2=t[k].lazy1*t[k<<1].lazy2+t[k].lazy2;t[k<<1].lazy2%=mod;t[k<<1|1].lazy2=t[k].lazy1*t[k<<1|1].lazy2+t[k].lazy2;t[k<<1|1].lazy2%=mod;t[k].lazy1=1;t[k].lazy2=0;
}

然后是乘的updata 要注意lazy2也要更新(当前的乘变了 加lazy也要变)

void updata1(int k,int l,int r,int val){if(l<=t[k].l&&t[k].r<=r){t[k].sum*=val;t[k].sum%=mod;//if(t[k].l<t[k].r) {t[k].lazy1*=val;t[k].lazy1%=mod;t[k].lazy2*=val;t[k].lazy2%=mod;//}}else{pushdown(k);int mid=(t[k].l+t[k].r)>>1;if(l<=mid) updata1(k<<1,l,r,val);if(mid<r) updata1(k<<1|1,l,r,val);pushup(k);}
}

改了好多次啊老是不对
感谢lc大佬帮看代码
and
这篇好好留着 要注意加乘顺序对lazy的影响 多个地方都需要修改lazy更改顺序!!!

下面是AC代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define inf 0x3f3f3f3f
#define sd(a) scanf("%d",&a)
#define sdd(a,b) scanf("%d%d",&a,&b)
#define cl(a,b) memset(a,b,sizeof(a))
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define sddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define dbg() printf("aaa\n")
using namespace std;
const int maxn=1e5+10;
int n,m,mod;
ll a[maxn];
struct node{int l,r;ll sum,lazy1,lazy2;//lazy1是乘 lazy2是加
}t[maxn<<2];
void pushup(int k){t[k].sum=(t[k<<1].sum+t[k<<1|1].sum)%mod;
}
void pushdown(int k){t[k<<1].sum*=t[k].lazy1;t[k<<1].sum%=mod;t[k<<1|1].sum*=t[k].lazy1;t[k<<1|1].sum%=mod;t[k<<1].lazy1*=t[k].lazy1;t[k<<1].lazy1%=mod;t[k<<1|1].lazy1*=t[k].lazy1;t[k<<1|1].lazy1%=mod;t[k<<1].sum+=t[k].lazy2*(t[k<<1].r-t[k<<1].l+1);t[k<<1].sum%=mod;t[k<<1|1].sum+=t[k].lazy2*(t[k<<1|1].r-t[k<<1|1].l+1);t[k<<1|1].sum%=mod;t[k<<1].lazy2=t[k].lazy1*t[k<<1].lazy2+t[k].lazy2;t[k<<1].lazy2%=mod;t[k<<1|1].lazy2=t[k].lazy1*t[k<<1|1].lazy2+t[k].lazy2;t[k<<1|1].lazy2%=mod;t[k].lazy1=1;t[k].lazy2=0;
}
void build(int k,int l,int r){t[k].l=l,t[k].r=r,t[k].lazy1=1,t[k].lazy2=0;if(l==r){t[k].sum=a[l]%mod;}else{int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);}
}
void updata1(int k,int l,int r,int val){if(l<=t[k].l&&t[k].r<=r){t[k].sum*=val;t[k].sum%=mod;//if(t[k].l<t[k].r) {t[k].lazy1*=val;t[k].lazy1%=mod;t[k].lazy2*=val;t[k].lazy2%=mod;//}}else{pushdown(k);int mid=(t[k].l+t[k].r)>>1;if(l<=mid) updata1(k<<1,l,r,val);if(mid<r) updata1(k<<1|1,l,r,val);pushup(k);}
}
void updata2(int k,int l,int r,int val){if(l<=t[k].l&&t[k].r<=r){t[k].sum+=(t[k].r-t[k].l+1)*val;t[k].sum%=mod;//if(t[k].l<t[k].r) {t[k].lazy2+=val;t[k].lazy2%=mod;//}}else{pushdown(k);int mid=(t[k].l+t[k].r)>>1;if(l<=mid) updata2(k<<1,l,r,val);if(mid<r) updata2(k<<1|1,l,r,val);pushup(k);}
}
ll query(int k,int l,int r){if(l<=t[k].l&&t[k].r<=r){return t[k].sum%mod;}else{pushdown(k);int mid=(t[k].l+t[k].r)>>1;ll ans=0;if(l<=mid) ans+=query(k<<1,l,r);ans%=mod;if(mid<r) ans+=query(k<<1|1,l,r);ans%=mod;return ans;}
}
int main(){sddd(n,m,mod);rep(i,1,n){scanf("%lld",&a[i]);}build(1,1,n);rep(i,1,m){int op,l,r,val;sd(op);if(op==1){sddd(l,r,val);updata1(1,l,r,val);}else if(op==2){sddd(l,r,val);updata2(1,l,r,val);}else if(op==3){sdd(l,r);ll ans=query(1,l,r)%mod;printf("%lld\n",ans);}}return 0;
}

题目描述
如题,已知一个数列,你需要进行下面三种操作:

将某区间每一个数乘上 xx

将某区间每一个数加上 xx

求出某区间每一个数的和

输入格式
第一行包含三个整数 n,m,pn,m,p,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含 nn 个用空格分隔的整数,其中第 ii 个数字表示数列第 ii 项的初始值。

接下来 mm 行每行包含若干个整数,表示一个操作,具体如下:

操作 11: 格式:1 x y k 含义:将区间 [x,y][x,y] 内每个数乘上 kk

操作 22: 格式:2 x y k 含义:将区间 [x,y][x,y] 内每个数加上 kk

操作 33: 格式:3 x y 含义:输出区间 [x,y][x,y] 内每个数的和对 pp 取模所得的结果

输出格式
输出包含若干行整数,即为所有操作 33 的结果。

输入输出样例
输入 #1复制
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4
输出 #1复制
17
2
说明/提示
【数据范围】

对于 30%30% 的数据:n \le 8n≤8,m \le 10m≤10
对于 70%70% 的数据:n \le 10^3n≤10
3
,m \le 10^4m≤10
4

对于 100%100% 的数据:n \le 10^5n≤10
5
,m \le 10^5m≤10
5

除样例外,p = 571373p=571373

洛谷 P3373 线段树模板题相关推荐

  1. 洛谷P3373线段树

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

  2. 洛谷 P3373 线段树2

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

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

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

  4. 洛谷3373 线段树模板

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

  5. 洛谷P3373线段树2

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

  6. 线段树模板题3:区间染色问题

    1.3线段树模板题3:区间染色问题 在DotA游戏中,帕吉的肉钩实际上是大多数英雄中最恐怖的东西.挂钩由长度相同的几个连续的金属棍组成. 现在,帕吉(Pudge)希望对挂接进行一些操作. 让我们将钩子 ...

  7. J.哭泣的阿木木(线段树模板题)

    哭泣的阿木木 Description 没啥用的背景故事: 在远古的恕瑞玛,有一个孤独而又忧郁的灵魂,阿木木.他在世间游荡,只为找到一个朋友.他遭受了一种远古的巫术诅咒,注定忍受永世的孤单,因为被他触碰 ...

  8. hdu1156(简单线段树 模板题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  9. 【线段树】[LUOGU 守墓人] [LUOGU 维护序列] 线段树模板题

    题目: 题目链接:[LUOGU 守墓人] 题解: 线段树单点修改,区间修改,单点查询,区间查询,一系列线段树基本操作,模板打就好. (回头再补一个分块和树状数组的这种板子题,就是用分块和树状数组再写一 ...

最新文章

  1. jsp mysql 换行_jsp 操作 mysql 数据库
  2. Macbook air 键盘标点符号怎么输出?
  3. 【总结】超1000页有三AI文档资源领取方法汇总!
  4. 视觉SLAM学习--RGB-D SLAM学习(待完善)
  5. 再谈类别不平衡问题:调节权重与魔改Loss的综合分析
  6. [Linux] Vmware 15安装CentOs后显示网络不可用
  7. 排序算法--(冒泡排序,插入排序,选择排序,归并排序,快速排序,桶排序,计数排序,基数排序)
  8. android编辑框最大字数,TextView 限制最大行数、最小行数、字数超过“...”表示...
  9. mysql between 等于_MySQL中BETWEEN子句的用法详解
  10. C语言斐波那契的递归函数 Fibonacci
  11. mapreduce排序比较器的选取
  12. 全屏幕文本编辑器___Q10的设置:
  13. Http 四种请求访问代码 HttpGet HttpPost HttpPut HttpDelete
  14. poj 2503 Babelfish
  15. 硬盘如何分区及分区注意事项
  16. 变频电源基本控制电路系统
  17. 南科大副教授“跳槽”到深圳中学引热议!大学老师不香了吗?
  18. LOL自制皮肤0-介绍我自己
  19. Vulkan教程 - 01 环境搭建
  20. html代码中文乱码解决

热门文章

  1. 小白必看 APN/证书/越狱等名词详解
  2. Android 集成facebook 登录和分享
  3. Unity 3d 摄像头
  4. 推荐几款极简的手机浏览器
  5. Python爬虫面试简历 经验分析
  6. android room 教程,Android Room的使用详解
  7. 文章推荐列表(个人收藏)
  8. 计算机网络中可使用的数据通信方式,计算机网络中的数据通信交换技术分析
  9. Python3,5行代码让电脑永不息屏。
  10. 木瓜移动全方位布局跨境电商SaaS木瓜大橙, 这条新赛道有何机遇?