洛谷P2023:https://www.luogu.org/problemnew/show/P2023

思路

需要2个Lazy-Tag

一个表示加的 一个表示乘的

需要先计算乘法 再计算加法

来自你谷milkfilling大佬的解释:

①加法优先,即规定好segtree[root*2].value=((segtree[root*2].value+segtree[root].add)*segtree[root].mul)%p,问题是这样的话非常不容易进行更新操作,假如改变一下add的数值,mul也要联动变成奇奇怪怪的分数小数损失精度,我们内心是很拒绝的;

②乘法优先,即规定好segtree[root*2].value=(segtree[root*2].value*segtree[root].mul+segtree[root].add*(本区间长度))%p,这样的话假如改变add的数值就只改变add,改变mul的时候把add也对应的乘一下就可以了,没有精度损失,看起来很不错。

所以这道题就是模板题啦~

易错点会在代码中详细注释出来

代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 100007
#define ll long long
ll sum[maxn<<],add[maxn<<],mul[maxn<<],a[maxn],n,m,p;
void build(ll l,ll r,ll k)
{
mul[k]=;//初始化标记
if(l==r)
{
sum[k]=a[l]%p;
mul[k]=;
return;
}
ll mid=(l+r)>>;
build(l,mid,k<<);//左右子树构建
build(mid+,r,k<<|);
sum[k]=(sum[k<<]+sum[k<<|])%p;//维护sum值
}
void pushdown(ll l,ll r,ll mid,ll k)//标记下放
{
//先乘后加
if(mul[k]!=)//当有乘法标记 计算所有的值
{
sum[k<<]=(sum[k<<]*mul[k])%p;
sum[k<<|]=(sum[k<<|]*mul[k])%p;
mul[k<<]=(mul[k<<]*mul[k])%p;
mul[k<<|]=(mul[k<<|]*mul[k])%p;
add[k<<]=(add[k<<]*mul[k])%p;//加法标记也要乘
add[k<<|]=(add[k<<|]*mul[k])%p;
mul[k]=;//清除标记
}
if(add[k])//当有加法标记
{
sum[k<<]=(sum[k<<]+add[k]*(mid-l+)%p)%p;//左右子树计算 右子树不用+1
sum[k<<|]=(sum[k<<|]+add[k]*(r-mid)%p)%p;//注意这里要先算sum 再算add
add[k<<]=(add[k]+add[k<<])%p;//如果先算add 那再sum中的add值已经改变
add[k<<|]=(add[k]+add[k<<|])%p;//坑了我一个晚上(太弱了)
add[k]=;//清除标记
}
return;
}
void update1(ll x,ll y,ll v,ll l,ll r,ll k)//在定区间[x,y]加上v
{
if(l>=x&&r<=y)//如果整个区间包含
{
add[k]=(add[k]+v)%p;
sum[k]=(sum[k]+(r-l+)*v)%p;
return;
}
ll mid=(l+r)>>;
pushdown(l,r,mid,k);
if(x<=mid) update1(x,y,v,l,mid,k<<);
if(mid<y) update1(x,y,v,mid+,r,k<<|);
sum[k]=(sum[k<<]+sum[k<<|])%p;//计算标记下放之后的值
return;
}
void update2(ll x,ll y,ll v,ll l,ll r,ll k)//在定区间[x,y]乘上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;
}
ll mid=(l+r)>>;
pushdown(l,r,mid,k);
if(x<=mid) update2(x,y,v,l,mid,k<<);
if(mid<y) update2(x,y,v,mid+,r,k<<|);
sum[k]=(sum[k<<]+sum[k<<|])%p;//计算标记下放之后的值
return;
}
ll query(ll x,ll y,ll l,ll r,ll k)
{
if(l>=x&&r<=y) return sum[k]%p;
ll mid=(l+r)>>;
ll res=;
pushdown(l,r,mid,k);//标记下放
if(x<=mid) res+=query(x,y,l,mid,k<<);
res%=p;
if(y>mid) res+=query(x,y,mid+,r,k<<|);
return res%p;
}
int main()
{
cin>>n>>p;
for(ll i=;i<=n;i++) cin>>a[i];
cin>>m;
build(,n,);
for(ll i=;i<=m;i++)
{
ll x,y,z;
cin>>x;
if(x==)
{
cin>>x>>y>>z;
update2(x,y,z,,n,);
}
else if(x==)
{
cin>>x>>y>>z;
update1(x,y,z,,n,);
}
else if(x==)
{
cin>>x>>y;
cout<<query(x,y,,n,)<<endl;
}
}
}

【题解】洛谷P2023 [AHOI2009] 维护序列(线段树)的更多相关文章

  1. 洛谷 P2023 [AHOI2009]维护序列 || 线段树加法和乘法运算

    原理倒是非常简单.设原数为x,加法的lazytag为b,乘法的lazytag为a,操作数为c,那么原式为ax+b,乘上c后(ax+b)c=(ac)*x+b*c,加上c后(ax+b)+c=ax+(b+c ...

  2. 洛谷P2023 [AHOI2009]维护序列(线段树区间更新,区间查询)

    洛谷P2023 [AHOI2009]维护序列 区间修改 当我们要修改一个区间时,要保证 \(ax+b\) 的形式,即先乘后加的形式.当将区间乘以一个数 \(k\) 时,原来的区间和为 \(ax+b\) ...

  3. 洛谷 P2023 [AHOI2009]维护序列 题解

    P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中 ...

  4. 洛谷 P2023 [AHOI2009]维护序列

    P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中 ...

  5. [洛谷P2023] [AHOI2009]维护序列

    洛谷题目链接:[AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列 ...

  6. [P2023][AHOI2009]维护序列(线段树)

    题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...

  7. 洛谷 2023 [AHOI2009]维护序列

    洛谷 2023 [AHOI2009]维护序列 洛谷原题传送门 这个题也是一道经典的线段树模版(其实洛谷的模版二改一下输入顺序就能AC),其中包括区间乘法修改.区间加法修改.区间查询三个操作. 线段树的 ...

  8. BZOJ1798[Ahoi2009]维护序列——线段树

    题目描述     老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成.    有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2 ...

  9. [AHOI2009]维护序列 (线段树)

    题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...

随机推荐

  1. javaweb带属性的自定义标签

    带属性的自定义标签: 1.先在标签处理器中定义setter方法,建议把所有的属性类型都设置为String类型. package com.javaweb.tag; import java.io.IOEx ...

  2. 九 ServerSocketChannel

    ServerSocketChannel是一个可以监听进来的TCP连接的通道,就像标准IO的ServerSocket一样.ServerSocketChannel类在java.nio.channels包中 ...

  3. 基于easyUI实现权限管理系统(四)——用户管理

    此文章是基于 EasyUI+Knockout实现经典表单的查看.编辑 一. 相关文件介绍 1. user.jsp:用户管理界面 <!DOCTYPE html PUBLIC "-//W3 ...

  4. easyui grid 里的可编辑text 加清空图标

    $.extend($.fn.datagrid.defaults.editors, { text: { init: function (container, options) { var _opt = ...

  5. OpenLayers中的图层(转载)

    作者:田念明出处:http://www.cnblogs.com/nianming/本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法 ...

  6. 项目经验:GIS<MapWinGIS>建模第七天

    终天完成了管网地图的附加功能..实现了了管网与地图结合

  7. 【Android】Warning :uninstalling will remove the application data!

    最近从Android Studio向手机发布项目过程中经常出现, 问题虽小,但是开发过程中确实浪费时间. It is possible that issue is resolved by uninst ...

  8. 基于以太坊的Token开发步骤

    Token开发步骤 一.准备工具1.安装以太坊brew tap ethereum/ethereumbrew install ethereum2.node:brew install nodejs3.安装 ...

  9. wcf 配置与代码创建

    <behaviors> <serviceBehaviors> <behavior name="MyServiceBehavior"> <s ...

  10. 绘制播放音乐时的音波图形的View

    绘制播放音乐时的音波图形的View 这个效果类似于这个哦: 效果如下: 源码: MusicView.h 与 MusicView.m // // MusicView.h // Music // // C ...