洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
题目描述
如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.将某区间每一个数乘上x
3.求出某区间每一个数的和
输入输出格式
输入格式:
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出格式:
输出包含若干行整数,即为所有操作3的结果。
输入输出样例
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
17
2
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强^_^)
样例说明:

故输出应为17、2(40 mod 38=2)
代码:
#include<cstdio>
#define LL long long//开long long!!
using namespace std;
const int N=; int n,m,mod;
LL Sum[N<<],LazySum[N<<],LazyMult[N<<]; void read(int &now)
{
now=;int f=;char c=getchar();
while(c<''||c>'')
{
if(c=='-')f=-;
c=getchar();
}
while(c>=''&&c<='')now=(now<<)+(now<<)+c-'',c=getchar();
now*=f;
} void PushUp(int rt)
{
Sum[rt]=Sum[rt<<]+Sum[rt<<|];
}
void PushDown(int rt,int m)
{
if(LazyMult[rt]!=)//乘法标记需不为1
{
Sum[rt<<]*=LazyMult[rt];Sum[rt<<]%=mod;
Sum[rt<<|]*=LazyMult[rt];Sum[rt<<|]%=mod;
LazyMult[rt<<]*=LazyMult[rt];LazyMult[rt<<]%=mod;
LazyMult[rt<<|]*=LazyMult[rt];LazyMult[rt<<|]%=mod;
LazySum[rt<<]*=LazyMult[rt];LazySum[rt<<]%=mod;
LazySum[rt<<|]*=LazyMult[rt];LazySum[rt<<|]%=mod;
LazyMult[rt]=;
}
if(LazySum[rt])
{
Sum[rt<<]+=LazySum[rt]*(m-(m>>));Sum[rt<<]%=mod;
Sum[rt<<|]+=LazySum[rt]*(m>>);Sum[rt<<|]%=mod;
LazySum[rt<<]+=LazySum[rt];LazySum[rt<<]%=mod;
LazySum[rt<<|]+=LazySum[rt];LazySum[rt<<|]%=mod;
LazySum[rt]=;
}
}
void Build(int l,int r,int rt)
{
LazySum[rt]=;LazyMult[rt]=;
if(l==r)
{
scanf("%lld",&Sum[rt]);
return;
}
int m=(l+r)>>;
Build(l,m,rt<<);
Build(m+,r,rt<<|);
PushUp(rt);
}
void ModifyAdd(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R)
{
Sum[rt]+=v*(r-l+);Sum[rt]%=mod;
LazySum[rt]+=v;LazySum[rt]%=mod;
return;
}
PushDown(rt,r-l+);
int m=(l+r)>>;
if(L<=m) ModifyAdd(l,m,rt<<,L,R,v);
if(m<R) ModifyAdd(m+,r,rt<<|,L,R,v);
PushUp(rt);
}
void ModifyMult(int l,int r,int rt,int L,int R,int v)
{
if(L<=l && r<=R)
{//对于懒惰标记 乘法会影响加法,但加法并不会影响乘法
//所以加法标记必须也乘
Sum[rt]*=v;Sum[rt]%=mod;
LazySum[rt]*=v;LazySum[rt]%=mod;//更新乘法的同时更新加法
LazyMult[rt]*=v;LazyMult[rt]%=mod;
return;
}
PushDown(rt,r-l+);
int m=(l+r)>>;
if(L<=m) ModifyMult(l,m,rt<<,L,R,v);
if(m<R) ModifyMult(m+,r,rt<<|,L,R,v);
PushUp(rt);
}
LL QuerySum(int l,int r,int rt,int L,int R)
{
if(L<=l && r<=R) return Sum[rt];
PushDown(rt,r-l+);
int m=(l+r)>>;LL res=;
if(L<=m) res+=QuerySum(l,m,rt<<,L,R),res%=mod;
if(m<R) res+=QuerySum(m+,r,rt<<|,L,R),res%=mod;
return res;
} int main()
{
read(n);read(m);read(mod);
Build(,n,);
for(int i=;i<=m;i++)
{
int opt,a,b;
read(opt);read(a);read(b);
if(opt==)
{
int k;read(k);
ModifyMult(,n,,a,b,k);
}
else if(opt==)
{
int k;read(k);
ModifyAdd(,n,,a,b,k);
}
else
printf("%lld\n",QuerySum(,n,,a,b));
}
return ;
}
洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)的更多相关文章
- 线段树_区间加乘(洛谷P3373模板)
题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...
- 洛谷P3374(线段树)(询问区间和,支持单点修改)
洛谷P3374 //询问区间和,支持单点修改 #include <cstdio> using namespace std; ; struct treetype { int l,r,sum; ...
- 洛谷 - P1198 - 最大数 - 线段树
https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...
- 洛谷 P2391 白雪皑皑 线段树+优化
题目描述: 现在有 \(N\) 片雪花排成一列. Pty 要对雪花进行$ M $次染色操作,第 \(i\)次染色操作中,把\((i*p+q)%N+1\) 片雪花和第\((i*q+p)%N+1\)片雪花 ...
- 【洛谷】【线段树】P1471 方差
[题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...
- 【洛谷】【线段树】P1047 校门外的树
[题目描述:] 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……,L ...
- 【洛谷】【线段树】P1886 滑动窗口
[题目描述:] 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. [输入格式:] 输入一共 ...
- 【洛谷】【线段树】P3353 在你窗外闪耀的星星
[题目描述:] /* 飞逝的的时光不会模糊我对你的记忆.难以相信从我第一次见到你以来已经过去了3年.我仍然还生动地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀 ...
- 洛谷 P5280 - [ZJOI2019]线段树(线段树+dp,神仙题)
题面传送门 神仙 ZJOI,不会做啊不会做/kk Sooke:"这八成是考场上最可做的题",由此可见 ZJOI 之毒瘤. 首先有一个非常显然的转化,就是题目中的"将线段树 ...
随机推荐
- Ubuntu/Debian apt-get 404 Not Found Package Repository Errors,无法找到包的错误
最简单最常用的方法是,使用如下命令更新到新的版本: sudo apt-get dist-upgrade 但是这个方法有时候不一定能起作用,那么可以使用以下直接替换的命令: sudo sed -i -e ...
- 高级 Java 必须突破的 10 个知识点!
1.Java基础技术体系.JVM内存分配.垃圾回收.类装载机制.性能优化.反射机制.多线程.网络编程.常用数据结构和相关算法. 2.对面向对象的软件开发思想有清晰的认识.熟悉掌握常用的设计模式. 3. ...
- jenkins checkstyle:local variable hides a field
源代码: 1 2 3 4 5 6 7 8 //应用上下文 private static ApplicationContext applicationContext; public static voi ...
- QML C++插件dll引用
插件的创建非常简单,但是它可以复用,并且为不同的应用程序扩展类型.使用创建的插件是非常灵活的解决方案.关于插件一个很好的例子见QmlBook-In-Chinese 中最后一章介绍的例子. 本文主要备忘 ...
- windows系统实现mysql数据库数据库主从复制
环境: master mysql服务器 192.168.8.201 slave mysql服务器 192.168.8.89 目标: 实现主从复制 1.将MySQL5.5安装文件分别拷贝到两台机器的c盘 ...
- zookeeper3.4.6配置实现自动清理日志
在使用zookeeper过程中,我们知道,会有dataDir和dataLogDir两个目录,分别用于snapshot和事务日志的输出(默认情况下只有dataDir目录,snapshot和事务日志都保存 ...
- 罗克韦尔 Allen-Bradley MicroLogix 1400 查看、设置IP
=============================================== 2019/4/14_第1次修改 ccb_warlock == ...
- Ex 5_32 一台服务器当前有n个等待服务的顾客...第八次作业
设第i个客户需要等待的时间为ti,则n个客户需要总的等待时间为 ,因此,要使T最小,则要使 即可,所以,对所有的ti按升序进行排序和服务将得到最小的等待时间. package org.xiu68.ch ...
- dispatchers 设置
Oracle连接方式(dispatchers 设置) oracle 响应客户端请求有两种方式: 1 专有连接:用一个服务器进程响应一个客户端请求 2 共享连接:用一个分派器(dispatcher)响应 ...
- Oracle11g_OCM 课堂教学目录表
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...