线段树2(P3373)



感谢洛谷题解让我理清了这一撮标记
这里多了一个乘法操作,乘法的优先级高于加法。我们来思考一下有关标记的问题。
首先由两种操作,可以想到要有两个标记,一个标记乘法(mul[k]),一个标记加法(add[k])。
如果这一步是加法,就直接在原来的add上面增加即可(加法不会对mul产生影响)(这里的“原来的add”是指已经处理好加法,乘法关系的add),sum也按照线段树1的方式维护。
如果这一步是乘法,因为乘法的优先级高于加法,所以乘法会对当前的add产生影响,即add[k]要乘当前的数。mul[k],sum[k]直接乘当前的数即可。
再考虑一下标记下传。
子节点收到父亲节点的add和mul之后,我们就要考虑是先用父亲的add还是mul去更新子节点(即先乘再加还是先加再乘)。我们上面处理add的时候,就已经考虑到了mul对add的影响,如果这时候先加再乘,就会造成翻倍的错误,所以我们先乘再加(也就是先让子节点的add乘父节点的mul,再加上父节点的add)。sum[子节点]要先乘mul[父节点],再加上add[父节点]*(r-l+1)。
理清了两种标记之间的关系,剩下的就是线段树板子了。这里要注意建树的时候,mul[k]初始值为1,add[k]初始值为0。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=;
ll n,m,p;
ll val[N*],sum[N*],add[N*],mul[N*];
ll read()
{
char ch=getchar();
ll x=;bool f=;
while(ch<''||ch>'')
{
if(ch=='-')f=;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
if(f)x=-x;
return x;
}
void build(ll k,ll l,ll r)
{
mul[k]=;
if(l==r)
{
sum[k]=val[r];
return ;
}
ll mid=(l+r)>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
sum[k]=(sum[k<<]+sum[k<<|]+p)%p;
return;
}
void change(ll k,ll l,ll r,ll u)
{
add[k]=(mul[u]*add[k]%p+add[u])%p;//记得随时%p
mul[k]=(mul[k]*mul[u])%p;
sum[k]=(sum[k]*mul[u]%p+add[u]*(r-l+)%p)%p;
}
void pushdown(ll k,ll l,ll r)//标记下传
{
ll mid=(l+r)>>;
change(k<<,l,mid,k);
change(k<<|,mid+,r,k);
add[k]=;
mul[k]=;
return;
}
void Mul(ll k,ll l,ll r,ll x,ll y,ll v)
{
if(l>=x&&r<=y)
{
mul[k]=(mul[k]*v)%p;
add[k]=(add[k]*v)%p;
sum[k]=(sum[k]*v)%p;
return ;
}
pushdown(k,l,r);
ll mid=(l+r)>>;
if(x<=mid)
Mul(k<<,l,mid,x,y,v);
if(mid<y)
Mul(k<<|,mid+,r,x,y,v);
sum[k]=(sum[k<<]+sum[k<<|]+p)%p;
return;
}
void Add(ll k,ll l,ll r,ll x,ll y,ll v)
{
if(l>=x&&r<=y)
{
add[k]=add[k]+v;
sum[k]=(sum[k]+v*(r-l+)%p)%p;
return ;
} pushdown(k,l,r);
ll mid=(l+r)>>;
if(x<=mid)
Add(k<<,l,mid,x,y,v);
if(mid<y)
Add(k<<|,mid+,r,x,y,v);
sum[k]=(sum[k<<]+sum[k<<|]+p)%p;
return ;
}
ll query(ll k,ll l,ll r,ll x,ll y)
{
if(l>=x&&r<=y)
return sum[k]%p;
pushdown(k,l,r);
ll mid=(l+r)>>;
ll ans=;
if(x<=mid)
ans+=query(k<<,l,mid,x,y);
if(mid<y)
ans+=query(k<<|,mid+,r,x,y);
return (ans+p)%p; //防止出现负数
}
int main()
{
n=read();m=read();p=read();
for(int i=;i<=n;i++)
val[i]=read()%p;
build(,,n);
for(int i=;i<=N*;i++)
mul[i]=;
for(int i=;i<=m;i++)
{
ll cz,x,y;
cz=read();x=read();y=read();
if(cz==)
{
ll k=read();
Mul(,,n,x,y,k);
}
if(cz==)
{
ll k=read();
Add(,,n,x,y,k);
}
if(cz==)
{
printf("%lld\n",query(,,n,x,y));
}
}
}
线段树2(P3373)的更多相关文章
- [线段树]Luogu P3373 【模板】线段树 2
#include<cstdio> #include<cstring> #include<algorithm> #define R register #define ...
- 洛谷P3373 【模板】线段树 2
P3373 [模板]线段树 2 47通过 186提交 题目提供者HansBug 标签 难度提高+/省选- 提交 讨论 题解 最新讨论 为啥WA(TAT) 题目描述 如题,已知一个数列,你需要进行 ...
- 洛谷 P3373 【模板】线段树 2 解题报告
P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上\(x\) 2.将某区间每一个数加上\(x\) 3.求出某区间每一个数的和 输入输出格式 ...
- 洛谷P3373线段树模板2
题目:https://www.luogu.org/problemnew/show/P3373 带乘的线段树,更新时把加的标记也乘一下,然后取值时先乘后加. 代码如下: #include<iost ...
- AC日记——【模板】线段树 2 洛谷 P3373
P3373 [模板]线段树 2387通过1.8K提交标签难度 提高+/省选- 提交 讨论 题解 最新讨论 更多讨论 2333最后三个点卡常数.迷之RE感觉这题很迷啊好像一共三组测试数据.友情提示:开l ...
- 洛谷——P3373 【模板】线段树 2&& B 数据结构
P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 线段树维护区间乘法 1.如何 ...
- 洛谷 P3373 【模板】线段树 2
洛谷 P3373 [模板]线段树 2 洛谷传送门 题目描述 如题,已知一个数列,你需要进行下面三种操作: 将某区间每一个数乘上 xx 将某区间每一个数加上 xx 求出某区间每一个数的和 输入格式 第一 ...
- 洛谷 P3373 【模板】线段树 2 题解
P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式 第一行包含三个整数 ...
- 【原创】洛谷 LUOGU P3373 【模板】线段树2
P3373 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第 ...
- P3373 【模板】线段树 2 (未完待续)
P3373 [模板]线段树 2 强烈安利这个大佬 超赞!!! 题解 本来以为这个题拿着线段树1的板子改改就好了,但是发现事情并没有那么简单,改了两天... 我们看到这个题其实涉及啦乘法和加法两种运算, ...
随机推荐
- 20190925 On Java8 第二十二章 枚举
第二十二章 枚举 基本 enum 特性 创建 enum 时,编译器会为你生成一个相关的类,这个类继承自 Java.lang.Enum. valueOf() 是在 Enum 中定义的 static 方法 ...
- Oracle数据库SQL语句的分类
1986年10月,美国国家标准协会对SQL进行规范后,以此作为关系式数据库管理系统的标准语言,1987年在国际标准组织的支持下成为国际标准.不过各种通行的数据库系统其实在实践过程中都对SQL规范的作了 ...
- linux驱动模型——platform(1)
一.驱动模型包含什么? 1.1. 类class 1.1.2. 它能够自动创建/dev下的设备节点,不需要mknod /dev/xxx c x x创建.当然class还有其另外的作用,且自动创建设备节点 ...
- IDEA中Java目录结构
IDEA中Java的目录结构 1.首先新建Project,选择Empty,新建空的项目 2.选择Module时候,需要选择JDK,JDK只需要选择到Java Home目录就可以了 3.创建好Modul ...
- 2019牛客暑期多校训练营(第三场) - J - LRU management - 模拟
https://ac.nowcoder.com/acm/contest/883/J 根据这个数据结构的特点,也就是计算机组成原理里面学过的cache的LRU管理算法,每次访问都会在cache中查询一页 ...
- 5.MCScanX 与circos下载、安装、运用
一.MCSCAN 参考 :http://chibba.pgml.uga.edu/mcscan2/MCScanX.zip http://chibba.pgml.uga.edu/mcscan2/#tm ...
- 通过express来打造api服务器
通过express来打造api服务器[ 后端接口 ] 1.步骤 1.通过脚手架创建项目 const express = require('express'); const router = expre ...
- Linux安装postgresql及基础操作
安装环境说明 系统环境说明 [root@slave1 ~]# cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) [root@sl ...
- 初步理解React
1.组件化 在 MV* 架构出现之前,组件主要分为两种: 狭义上的组件,又称为 UI 组件,比如 Tabs 组件.Dropdown 组件.组件主要围绕在交互 动作上的抽象,针对这些交互动作,利用 Ja ...
- Oracle Set操作
并集合 union/uinon all union 会去重,uinon all 不去重 交集 intersect 差集 minus