线段树——区间累加、区间累乘、区间求和
题目链接
题解:
这道题目的难点在于如何考虑加法和乘法的”兼容“问题
定义两个标记 mul_lazy 和 add_lazy 分别表示加法和乘法
默认乘法优先 :因为算术运算中乘法优先级高,add_lazy标记可能还没有下放,如果默认加法优先,修改mul_lazy可能会导致错误
所以 每次乘的时候,子节点mul_lazy和add_lazy都一起乘父节点的mul_lazy,加的时候 子节点的add_lazy加父节点的add_lazy即可
push_down的更新操作代码
1 struct node 2 { 3 int l,r; 4 ll sum,add_lazy,mul_lazy; 5 void update(ll mul,ll add) 6 { 7 if(mul!=1) 8 { 9 mul_lazy=(mul_lazy*mul)%mod; 10 add_lazy=(add_lazy*mul)%mod; 11 sum=(sum*mul)%mod; 12 } 13 if(add) 14 { 15 add_lazy=(add_lazy+add)%mod; 16 sum=(sum+((r-l+1)*add))%mod; 17 } 18 } 19 }tree[maxn<<2];
View Code
可以发现上面push_down的更新操作,加法和乘法可以合并
合并代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 int n,a[maxn],q,mod; 6 struct node 7 { 8 int l,r; 9 ll sum,add_lazy,mul_lazy; 10 void update(ll mul,ll add) 11 { 12 sum=(sum*mul+add*(r-l+1))%mod; 13 mul_lazy=(mul_lazy*mul)%mod; 14 add_lazy=(add_lazy*mul+add)%mod; 15 16 } 17 }tree[maxn<<2]; 18 19 void push_up(int x) 20 { 21 tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%mod; 22 } 23 void push_down(int x) 24 { 25 int mul=tree[x].mul_lazy; 26 int add=tree[x].add_lazy; 27 if(mul!=1 || add!=0) 28 { 29 tree[x<<1].update(mul,add); 30 tree[x<<1|1].update(mul,add); 31 tree[x].add_lazy=0; 32 tree[x].mul_lazy=1; 33 } 34 } 35 void build(int x,int l,int r) 36 { 37 tree[x].l=l,tree[x].r=r; 38 tree[x].add_lazy=tree[x].sum=0; 39 tree[x].mul_lazy=1; 40 if(l==r) 41 { 42 tree[x].sum=a[l]; 43 } 44 else 45 { 46 int mid=(l+r)>>1; 47 build(x<<1,l,mid); 48 build(x<<1|1,mid+1,r); 49 push_up(x); 50 } 51 } 52 void update(int x,int l,int r,ll val,int flag) 53 { 54 int L=tree[x].l,R=tree[x].r; 55 56 if(l<=L && R<=r) 57 { 58 if(flag==1)tree[x].update(val,0); 59 else tree[x].update(1,val); 60 } 61 else 62 { 63 push_down(x); 64 int mid=(L+R)>>1; 65 if(mid>=l)update(x<<1,l,r,val,flag); 66 if(mid<r)update(x<<1|1,l,r,val,flag); 67 push_up(x); 68 } 69 } 70 ll query(int x,int l,int r) 71 { 72 int L=tree[x].l,R=tree[x].r; 73 74 if(l<=L && R<=r) 75 { 76 return tree[x].sum%mod; 77 } 78 else 79 { 80 push_down(x); 81 ll ans=0; 82 int mid=(L+R)>>1; 83 if(mid>=l)ans+=query(x<<1,l,r)%mod; 84 if(mid<r)ans+=query(x<<1|1,l,r)%mod; 85 push_up(x); 86 return ans%mod; 87 } 88 89 } 90 int main() 91 { 92 scanf("%d%d%d",&n,&q,&mod); 93 for(int i=1;i<=n;i++) 94 scanf("%d",&a[i]); 95 build(1,1,n); 96 for(int i=1;i<=q;i++) 97 { 98 int l,r,op; 99 ll val; 100 scanf("%d",&op); 101 if(op==1) 102 { 103 scanf("%d%d%lld",&l,&r,&val); 104 update(1,l,r,val,op); 105 } 106 else if(op==2) 107 { 108 scanf("%d%d%lld",&l,&r,&val); 109 update(1,l,r,val,op); 110 } 111 else 112 { 113 scanf("%d%d",&l,&r); 114 printf("%lld\n",query(1,l,r)); 115 } 116 117 118 } 119 return 0; 120 }
View Code
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+5; 5 int n,a[maxn],q,mod; 6 struct node 7 { 8 int l,r; 9 ll sum,add_lazy,mul_lazy; 10 void update(ll mul,ll add) 11 { 12 if(mul!=1) 13 { 14 mul_lazy=(mul_lazy*mul)%mod; 15 add_lazy=(add_lazy*mul)%mod; 16 sum=(sum*mul)%mod; 17 } 18 if(add) 19 { 20 add_lazy=(add_lazy+add)%mod; 21 sum=(sum+((r-l+1)*add))%mod; 22 } 23 ///合并代码 24 /* 25 sum=(sum*mul+add*(r-l+1))%mod; 26 mul_lazy=(mul_lazy*mul)%mod; 27 add_lazy=(add_lazy*mul+add)%mod; 28 */ 29 30 } 31 }tree[maxn<<2]; 32 33 void push_up(int x) 34 { 35 tree[x].sum=(tree[x<<1].sum+tree[x<<1|1].sum)%mod; 36 } 37 void push_down(int x) 38 { 39 int mul=tree[x].mul_lazy; 40 int add=tree[x].add_lazy; 41 if(mul!=1 || add!=0) 42 { 43 tree[x<<1].update(mul,add); 44 tree[x<<1|1].update(mul,add); 45 tree[x].add_lazy=0; 46 tree[x].mul_lazy=1; 47 } 48 } 49 void build(int x,int l,int r) 50 { 51 tree[x].l=l,tree[x].r=r; 52 tree[x].add_lazy=tree[x].sum=0; 53 tree[x].mul_lazy=1; 54 if(l==r) 55 { 56 tree[x].sum=a[l]; 57 } 58 else 59 { 60 int mid=(l+r)>>1; 61 build(x<<1,l,mid); 62 build(x<<1|1,mid+1,r); 63 push_up(x); 64 } 65 } 66 void update(int x,int l,int r,ll val,int flag) 67 { 68 int L=tree[x].l,R=tree[x].r; 69 70 if(l<=L && R<=r) 71 { 72 if(flag==1)tree[x].update(val,0); 73 else tree[x].update(1,val); 74 } 75 else 76 { 77 push_down(x); 78 int mid=(L+R)>>1; 79 if(mid>=l)update(x<<1,l,r,val,flag); 80 if(mid<r)update(x<<1|1,l,r,val,flag); 81 push_up(x); 82 } 83 } 84 ll query(int x,int l,int r) 85 { 86 int L=tree[x].l,R=tree[x].r; 87 88 if(l<=L && R<=r) 89 { 90 return tree[x].sum%mod; 91 } 92 else 93 { 94 push_down(x); 95 ll ans=0; 96 int mid=(L+R)>>1; 97 if(mid>=l)ans+=query(x<<1,l,r)%mod; 98 if(mid<r)ans+=query(x<<1|1,l,r)%mod; 99 push_up(x); 100 return ans%mod; 101 } 102 103 } 104 int main() 105 { 106 scanf("%d%d%d",&n,&q,&mod); 107 for(int i=1;i<=n;i++) 108 scanf("%d",&a[i]); 109 build(1,1,n); 110 for(int i=1;i<=q;i++) 111 { 112 int l,r,op; 113 ll val; 114 scanf("%d",&op); 115 if(op==1) 116 { 117 scanf("%d%d%lld",&l,&r,&val); 118 update(1,l,r,val,op); 119 } 120 else if(op==2) 121 { 122 scanf("%d%d%lld",&l,&r,&val); 123 update(1,l,r,val,op); 124 } 125 else 126 { 127 scanf("%d%d",&l,&r); 128 printf("%lld\n",query(1,l,r)); 129 } 130 131 132 } 133 return 0; 134 }
View Code
转载于:https://www.cnblogs.com/j666/p/11508889.html
线段树——区间累加、区间累乘、区间求和相关推荐
- 线段树线段树的创建线段树的查询单节点更新区间更新
目录 线段树 什么是线段树? 线段树的创建 线段树的查询 单节点更新 区间更新 未完待续 线段树 实现问题:常用于求数组区间最小值 时间复杂度:(1).建树复杂度:nlogn.(2).线段树算法复杂度 ...
- 【线段树】HDU 3397 Sequence operation 区间合并
操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...
- 线段树优化建图详解——区间连边之技巧,吊打紫题之利器
我们从一道例题开始. CF786B Description Solution 朴素解法: 暴力连边+最短路 对于每次连边操作,我们逐一连边,最后在图上跑一遍单源最短路径算法即可. 时间复杂度 O ( ...
- 线段树(成段更新,区间求和lazy操作 )
hdu1556 Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/O ...
- 题目敌兵布阵-------线段树(单点修改查询,区间修改查询)
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...
- 线段树POJ3468(成段更新,区间求和)
题目:A Simple Problem with Integers #include <stdio.h> #define N 111111 #define LL long long #de ...
- HDU-1754 线段树的节点更新,储存区间的最大值
很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师 ...
- 线段树为什么要开四倍区间大小的数组
我的想法是,不能理解它,那就记住它!! 但是这里有大佬的想法,欢迎参观:https://blog.csdn.net/smoggyxhdz/article/details/78895672
- szu 寒训个人复习第一天 线段树入门单点修改,区间修改,以及线段树的扩展运用[线段树+dp][区间最大公约数]
寒讯内容有点过多(其实是我太菜了)水一波怕忘了(人老了)**什么是线段树** 线段树是本蒟蒻感觉用处特别大的算法 那么线段树上面的节点表示什么意思呢? 线段树,上面的节点表示一个区间,父亲节点表示的区 ...
- HDU - 3667 Hotel(线段树+区间合并)
题目链接:点击查看 题目大意:给出n个连续的空房间,依次进行m个操作,操作一是查询操作,查询在总区间内的一段连续的长度为x的空房间,并 且该位置要靠左,如果查询到返回最左边的端点,并将其占用,找不到返 ...
最新文章
- oracle votedisk 参数,11g r2 rac votedisk 及 ocr 磁盘破坏后,基于ocr备份的恢复步骤
- 「高并发秒杀」java课程设计报告模板
- 辨析Java与Javascript
- 1040 Longest Symmetric String (25 分)【难度: 一般 / 知识点: 最长回文子串】
- 2013ACM暑假集训总结-致将走上大三征途的我
- 数据结构与算法(C++)– 贪婪算法(Greedy algorithm)
- 关掉linux下的讨厌的beep声
- cocos2d-x游戏实例(3)-获得地图索引
- json 取值判断_【收藏级】.NETCore3.1中的Json互操作解读
- java学习(34):巩固练习
- c语言while求a和b的和程序,数据结构实验1_C语言_输入集合A和B求并集、交集、差集(while +...
- 中国糖和甜味剂市场趋势报告、技术动态创新及市场预测
- 计算机在生产作业管理,作业管理
- windows环境下面安装neo4j出错记录
- title或alt自动换行
- CSS3渐变(Gradients)-线性渐变
- 计算机关机又自动重启,电脑关机后自动重启是什么原因?Win10关机变重启原因及解决方法...
- 雷达系统和雷达信号分析02
- 什么是蜂窝移动网络?
- python计算学习,《统计学习方法》的Python实现:(1)感知机