线段树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的板子改改就好了,但是发现事情并没有那么简单,改了两天... 我们看到这个题其实涉及啦乘法和加法两种运算, ...
随机推荐
- 003/kubernetes基础:开启云原生之门(Mooc)
一.简介:(https://www.imooc.com/learn/978) 在2017年Kubernetes战胜了两个强大的竞争对手Swarm和Mesos,成为容器管理与调度编排领域的首选平台和事实 ...
- Mac--PHP已经开启gd扩展验证码不显示
错误显示:Call to undefined function imagettftext() 原因: mac系统中自带的php的gd库中,缺少对freetype的支持,导致图片无法显示. 解决: 1 ...
- jdk下载安装后为什么要设置环境变量?
因为电脑不知道javac这个命令是在C:\Program Files\JAVA\jdk1.8.0_65\bin的这个路径下面,所以我们要设置好环境变量,来让电脑知道其路径
- [BZOJ 2199] [USACO11JAN] 大陆议会The Continental Cowngress(2-SAT)
[BZOJ 2199] [USACO11JAN] 大陆议会The Continental Cowngress(2-SAT) 题面 题面较长,略 分析 考虑把问题转化成一个依赖性问题 我们把每只奶牛投出 ...
- Codeforces 429E(欧拉回路)
题面 传送门 题目大意: 有n条线段,每条线段染红色或蓝色,使得数轴上每个点被红色线段覆盖的次数与被蓝色线段覆盖数差的绝对值小于等于1.输出染色方案. 分析 题意其实可以这样理解: 一段初始全为0 的 ...
- js+css实现点击回到顶部的效果(最低兼容至ie7)
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 【python】pyenv与virtualenv安装,实现python多版本多项目管理
踩了很多坑,记录一下这次试验,本次测试环境:Linux centos7 64位. pyenv是一个python版本管理工具,它能够进行全局的python版本切换,也可以为单个项目提供对应的python ...
- Java中数组在内存中的存放原理?
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyong0717/article/details/79165685Java中数组被实现为对象, ...
- 【转载】Mysql注入点在limit关键字后面的利用方法
描写sql注入利用方法的文章数不胜数,本文将描述一种比较特殊的场景. 细节 在一次测试中,我碰到了一个sql注入的问题,在网上没有搜到解决办法,当时的注入点是在limit关键字后面,数据库是MyS ...
- 学习python os commands socket模块
import os print(os.getcwd()) #获取当前路径, 导包也是从这个路径下面才能找到 # os.chdir('./..') #返回上一级路径,再获取路径看看 # print(os ...