洛谷P3373 【模板】线段树2
来源:互联网 发布:孢子mac中文版下载 编辑:程序博客网 时间:2024/06/05 16:33
这题有毒啊,敲了我一晚上加一早上,总算A了。
由于有加和乘两个操作,要用2个lazy数组。
核心难点就是2个lazy数组会相互影响。
因为乘影响加,加不影响乘,所以我们先算乘。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <set>#include <map>#include <vector>#include <list>#define rep(i,m,n) for(int i=m;i<=n;i++)#define dop(i,m,n) for(int i=m;i>=n;i--)#define lowbit(x) (x&(-x)) #define ll long long#define INF 2147483647using namespace std;inline int read(){ //不写快读据说可能TLE int s=0,w=1; char ch=getchar(); while(ch<='0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;}const int maxn=100000;ll a[maxn+10],sum[(maxn<<2)+10],n,m,b,c,d,e,add[(maxn<<2)+10],mul[(maxn<<2)+10],mod; //安全起见,都开long longvoid PushDown(int now,int m){ //now:线段编号,m:线段长度 if(mul[now]!=1){ //乘法lazy数组都赋值为1 mul[now<<1]*=mul[now]; mul[now<<1|1]*=mul[now]; sum[now<<1]*=mul[now]; sum[now<<1|1]*=mul[now]; add[now<<1]*=mul[now]; add[now<<1|1]*=mul[now]; mul[now<<1]%=mod; mul[now<<1|1]%=mod; sum[now<<1]%=mod; sum[now<<1|1]%=mod; add[now<<1]%=mod; add[now<<1|1]%=mod; mul[now]=1; } if(add[now]){ add[now<<1]+=add[now]; add[now<<1|1]+=add[now]; sum[now<<1]+=add[now]*(m-(m>>1)); sum[now<<1|1]+=add[now]*(m>>1); add[now<<1]%=mod; //多mod几下,不会错 add[now<<1|1]%=mod; sum[now<<1]%=mod; sum[now<<1|1]%=mod; add[now]=0; }}void Build(int now,int l,int r){ //建树 mul[now]=1; if(l==r) sum[now]=a[l]; else{ int mid=(l+r)>>1; Build(now<<1,l,mid); Build(now<<1|1,mid+1,r); sum[now]=sum[now<<1]+sum[now<<1|1]; }}ll Query(int now,int l,int r,int wl,int wr){ //查询 if(l>wr||r<wl) return 0; if(l>=wl&&r<=wr) return sum[now]; PushDown(now,r-l+1); int mid=(l+r)>>1; return (Query(now<<1,l,mid,wl,wr)%mod+Query(now<<1|1,mid+1,r,wl,wr)%mod)%mod;}void Change(int now,int l,int r,int wl,int wr,int p,int mode){ //改值,mode=1:加法,mode=2:乘法 if(l>wr||r<wl) return; //如果当前区间不在需要改值的区间内,返回 if(l>=wl&&r<=wr){ //如果当前区间包括在需要改值的区间内,改这段的值,并标记lazy if(mode) add[now]+=p,sum[now]+=p*(r-l+1),add[now]%=mod,sum[now]%=mod; else mul[now]*=p,sum[now]*=p,add[now]*=p,add[now]%=mod,sum[now]%=mod,mul[now]%=mod; //如果是乘法,要把加法lazy的值也改掉(乘法分配率) return; } PushDown(now,r-l+1); int mid=(l+r)>>1; Change(now<<1,l,mid,wl,wr,p,mode); Change(now<<1|1,mid+1,r,wl,wr,p,mode); sum[now]=(sum[now<<1]+sum[now<<1|1])%mod;}int main(){ n=read();m=read();mod=read(); rep(i,1,n) a[i]=read(); Build(1,1,n); rep(i,1,m){ b=read(); if(b==1){ c=read();d=read();e=read(); Change(1,1,n,c,d,e,0); } if(b==2){ c=read();d=read();e=read(); Change(1,1,n,c,d,e,1); } if(b==3){ c=read();d=read(); printf("%lld\n",Query(1,1,n,c,d)); } } return 0;}
阅读全文
1 0
- 洛谷P3373 【模板】线段树2
- 洛谷 P3373 【模板】线段树 2 (线段树)
- P3373 【模板】线段树 2(区间增乘)
- 【模板】线段树 区间加+乘,区间求和 (模板题:洛谷P3373)
- 【BZOJ/Luogu】1798/P3373 [Ahoi2009]Seq 维护序列seq/【模板】线段树 2 区间加、乘线段树
- 线段树模板2
- 洛谷 PP3373【模板】线段树 2
- 【模板】线段树 洛谷 3372 线段树
- 洛谷 P3372 线段树模板
- 洛谷p3373(自己附上的解释)
- ACM 线段树模板(模板)
- 洛谷 3372_【模板】线段树 1_线段树
- 【洛谷】P3372线段树1 线段树模板
- 【洛谷1592】【模板】template 线段树 线段树裸题
- [luogu3373][模板]线段树 2(线段树)
- 【洛谷P3372】【模板】线段树 1
- 洛谷P3374模板线段树1
- 洛谷3372[模板]线段树1
- iOS界面调试工具 Reveal的安装和使用
- 测试
- 八.Spring的属性注入-注入对象,复杂的集合类型属性
- 【单片机笔记】有源蜂鸣器驱动-效率编程
- 子集生成
- 洛谷P3373 【模板】线段树2
- 欢迎使用CSDN-markdown编辑器
- MongoDB配置--docker进阶
- FCC----------- Arguments Optional
- 通过Json和Gson,快速生成和解析json字符串
- OpenCV编程->单目相机内参及畸变求解
- 列表中第一大和第二大元素
- SQL 操作列名
- Jquery_Ajax