洛谷 P3373 【模板】线段树 2

洛谷传送门

题目描述

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

  • 将某区间每一个数乘上 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复制

输出 #1复制

说明/提示

【数据范围】

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

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

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

除样例外,p = 571373p=571373

(数据已经过加强_

样例说明:

故输出应为 1717、22( 40 \bmod 38 = 240mod38=2 )

题解:

线段树模板维护区间乘和区间加,查询区间和。

如果对于简单线段树不是很了解的同学可以翻看本蒟蒻的这篇博客:

详解简单线段树

但是简单线段树并没有给出区间乘法的维护方法...

但我们可以参照区间加法进行类比。区间加法需要维护一个延迟标记,区间乘法当然也需要,由于乘法就是一连串的加法,所以我们在下传延迟标记的时候不仅需要下传乘法标记给线段树数组和子节点的乘法标记数组,还要把乘法标记下传给加法标记数组。也就是说:

线段树维护区间乘法的步骤为:

线段树数组乘标记,自己乘标记,加法数组乘标记。

加法的直接上简单线段树的板子即可。

注意,先乘后加!

代码:

#include<cstdio>
#define int long long
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=1e5+10;
int n,m,mod;
int a[maxn];
int tree[maxn<<2],lazy[maxn<<2],lazy2[maxn<<2];
void build(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
{
tree[pos]=a[l];
return;
}
build(lson,l,mid);
build(rson,mid+1,r);
tree[pos]=(tree[lson]+tree[rson])%mod;
}
void mark(int pos,int l,int r,int k,int flag)
{
if(flag)
{
tree[pos]=(tree[pos]*k)%mod;
lazy2[pos]=(lazy2[pos]*k)%mod;
lazy[pos]=(lazy[pos]*k)%mod;
}
else
{
tree[pos]=(tree[pos]+(r-l+1)*k)%mod;
lazy2[pos]=(lazy2[pos]+k)%mod;
}
}
void pushdown(int pos,int l,int r)
{
int mid=(l+r)>>1;
mark(lson,l,mid,lazy[pos],1);
mark(rson,mid+1,r,lazy[pos],1);
mark(lson,l,mid,lazy2[pos],0);
mark(rson,mid+1,r,lazy2[pos],0);
lazy2[pos]=0,lazy[pos]=1;
}
void update(int pos,int l,int r,int x,int y,int k,int flag)
{
int mid=(l+r)>>1;
if(x<=l && r<=y)
{
if(flag)
mark(pos,l,r,k,flag);
else
mark(pos,l,r,k,flag);
return;
}
pushdown(pos,l,r);
if(x<=mid)
update(lson,l,mid,x,y,k,flag);
if(y>mid)
update(rson,mid+1,r,x,y,k,flag);
tree[pos]=(tree[lson]+tree[rson])%mod;
}
int query(int pos,int l,int r,int x,int y)
{
int ret=0;
int mid=(l+r)>>1;
if(x<=l && r<=y)
return tree[pos]%mod;
pushdown(pos,l,r);
if(x<=mid)
ret=(ret+query(lson,l,mid,x,y))%mod;
if(y>mid)
ret=(ret+query(rson,mid+1,r,x,y))%mod;
return ret%mod;
}
signed main()
{
for(int i=1;i<=maxn<<2;i++)
lazy[i]=1,lazy2[i]=0;
scanf("%lld%lld%lld",&n,&m,&mod);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int opt,x,y,k;
scanf("%lld",&opt);
if(opt==1)
{
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k,1);
}
else if(opt==2)
{
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k,0);
}
else
{
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(1,1,n,x,y));
}
}
return 0;
}

洛谷 P3373 【模板】线段树 2的更多相关文章

  1. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  2. 线段树_区间加乘(洛谷P3373模板)

    题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...

  3. 洛谷 - P1198 - 最大数 - 线段树

    https://www.luogu.org/problemnew/show/P1198 要问区间最大值,肯定是要用线段树的,不能用树状数组.(因为没有逆元?但是题目求的是最后一段,可以改成类似前缀和啊 ...

  4. 洛谷 P2391 白雪皑皑 线段树+优化

    题目描述: 现在有 \(N\) 片雪花排成一列. Pty 要对雪花进行$ M $次染色操作,第 \(i\)次染色操作中,把\((i*p+q)%N+1\) 片雪花和第\((i*q+p)%N+1\)片雪花 ...

  5. 【洛谷】【线段树】P1471 方差

    [题目背景:] 滚粗了的HansBug在收拾旧数学书,然而他发现了什么奇妙的东西. [题目描述:] 蒟蒻HansBug在一本数学书里面发现了一个神奇的数列,包含N个实数.他想算算这个数列的平均数和方差 ...

  6. 【洛谷】【线段树】P1047 校门外的树

    [题目描述:] 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2,……,L ...

  7. 【洛谷】【线段树】P1886 滑动窗口

    [题目描述:] 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. [输入格式:] 输入一共 ...

  8. 【洛谷】【线段树】P3353 在你窗外闪耀的星星

    [题目描述:] /* 飞逝的的时光不会模糊我对你的记忆.难以相信从我第一次见到你以来已经过去了3年.我仍然还生动地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀 ...

  9. 洛谷P5280 [ZJOI2019]线段树

      https://www.luogu.org/problemnew/show/P5280 省选的时候后一半时间开这题,想了接近两个小时的各种假做法,之后想的做法已经接近正解了,但是有一些细节问题理不 ...

  10. 洛谷P3374(线段树)(询问区间和,支持单点修改)

    洛谷P3374 //询问区间和,支持单点修改 #include <cstdio> using namespace std; ; struct treetype { int l,r,sum; ...

随机推荐

  1. How to: Map a Persistent Class to a Database View Which Has No Key Field如何:映射持久化类到无主键数据库视图

    With XAF, you can build new applications from scratch or maintain existing databases. The How to: Ge ...

  2. 短信相关的AT指令以及信令

    本文链接:https://blog.csdn.net/sjz4860402/article/details/78552756 此次的短信AT指令和信令从以下几个方面介绍: 一 . 短信AT指令的格式二 ...

  3. 【Beta阶段】第十周Scrum会议

    [Beta阶段]第十周Scrum会议 本次会议为第十周第一次Scrum Meeting,会议对Alpha阶段的工作进行了反思总结,以及对Beta阶段工作的展望. 会议时间为2019.11.23.会议地 ...

  4. 生产环境Shell脚本Ping监控主机是否存活(多种方法)

    在网上针对shell脚本ping监控主机是否存活的文档很多,但大多都是ping一次就决定了状态,误报率会很高,为了精确判断,ping三次不通再发告警,只要一次ping通则正常.于是,今天中午抽出点时间 ...

  5. JavaScript-----8.数组

    1.数组的概念 数组是指一组数据的集合,其中每个数据被称为元素,在数组中可以存放任意类型的元素 2. 创建数组 创建数组的两种方式: 利用new创建数组 利用数组字面量创建数组(最常用) 2.1 利用 ...

  6. 2019-2020-1 20199305《Linux内核原理与分析》第七周作业

    进程的描述与创建 (一)进程的描述 (1)操作系统内核实现操作系统的三大管理功能(进程管理最为核心) 进程管理 内存管理 文件系统 (2)在Linux内中用一个数据结构struct task_stru ...

  7. java之List接口(单列集合)

    List接口概述 查询API我们可知:java.util.List 接口继承自 Collection 接口,是单列集合的一个重要分支,习惯性地会将实现了 List 接口的对 象称为List集合.在Li ...

  8. PHPStorm 初遇 Xdebug (xdebug代码调试及性能分析)

    centos 7 下PHP7安装xdebug # 下载xdebug wget https://xdebug.org/files/xdebug-2.7.2.tgz # 解压 tar -xf xdebug ...

  9. [考试反思]1110csp-s模拟测试108:消遣

    是套废题.T1题面错了,T2细节多而暴力>部分分,T3题目错了. T1:打表 题面应该是输出差值期望而不是答案值期望. 看到题目,果断打表. 答案就是所有值差之和除2的k次方. #include ...

  10. IT兄弟连 HTML5教程 HTML5做到了与之前版本的兼容

    为了保证HTML5能与之前的HTML版本达到最大的兼容,HTML5对一些元素标记的省略.boolean值的属性,以及引号的省略这几方面进行了兼顾,确保与之前版本的HTML达到兼容.在下面示例中,将本节 ...