洛谷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 之毒瘤. 首先有一个非常显然的转化,就是题目中的"将线段树 ...
随机推荐
- gpio_request 原形代码【转】
转自:http://blog.csdn.net/maopig/article/details/7428561 其原型为 int gpio_request(unsigned gpio, const ch ...
- 开发使用tomcat生产使用weblogic造成jar包冲突如何解决?
问题描述开发时新增了jar包,当将增量包部署到测试服务器后启动应用出现如下错误提示:java.lang.LinkageError: loader constraint violation: loade ...
- svn使用openldap验证apache访问方式
启用svn服务器的sasl验证机制 1.安装cyrus-sasl认证包 # yum install -y *sasl* # rpm -qa|grep sasl cyrus-sasl-2.1.23-15 ...
- I/O 接口及其编址方式
I/O 接口电路也简称接口电路.它是主机和外围设备之间交换信息的连接部件(电路).它在主机和外围设备之间的信息交换中起着桥梁和纽带作用.设置接口电路的必要性:a) 解决主机CPU 和外围设备之间的时序 ...
- css之hover改变子元素和其他元素样式
参考地址:链接 +表示下一级元素,>表示子元素 <!DOCTYPE html> <html> <head lang="en"> <m ...
- MySQL 5.6.26几种安装包的区别
一.MySQL Installer 5.6.26 mysql-installer-community-5.6.26.0.msi, 364.2MBMySQL Installer 提供了简单易用.向导式的 ...
- C++ code:判断字符串相等
如果两个字符串中0和1的个数分别相等,则称该对字符串为相等. 方法一: 由于string类对于读取文件中子串以及比较都很方便,所以,用string类的对象来逐对存放字串,然后将字串分别排序后对其进行比 ...
- [主席树 强制在线]ZOJ3888 Twelves Monkeys
题意:有n年,其中m年可以乘时光机回到过去,q个询问 下面m行,x,y 表示可以在y年穿越回x年, 保证y>x 下面q个询问, 每个询问有个年份k 问的是k年前面 有多少年可以通过一种以上($\ ...
- Java 变量、循环、判断
粗糙笔记不喜勿喷 Java 8大基本类型 第一类:逻辑型(boolean) 1.boolean类型只存在true(真),false(假)两种形式 例: boolean a=true; boolean ...
- linux常用软件安装,常用命令
jdk [root@localhost]# tar -zxvf jdk-8u144-linux-x64.tar.gz [root@localhost]# vi /etc/profile 在profil ...