洛谷P2023 [AHOI2009]维护序列

区间修改

当我们要修改一个区间时,要保证 \(ax+b\) 的形式,即先乘后加的形式。当将区间乘以一个数 \(k\) 时,原来的区间和为 \(ax+b\) ,乘以 \(k\) 得 \(k(ax+b)=kax+kb\) 。

区间加一个数更加简单,原来的区间和为 \(ax+b\) ,加上一个 \(k\) 为 \(ax+b+k\) ,合并 \(b\) ,\(k\) 得 \(ax+(b+k)\) 。

标记下传

\[a(a'x+b')+b = (aa')\cdot x + (ab'+b)
\]

#include<bits/stdc++.h>

using namespace std;
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1 const int maxn = 100005;
long long tree[maxn << 2];
int n, p, q;
struct L{
long long mul, add;
}label[maxn << 2]; inline void pushUp(int root)
{
tree[root] = (tree[root << 1] + tree[root << 1 | 1]) % p;
}
inline void pushDown(int root, int len)
{
if(label[root].add == 0 && label[root].mul == 1) return;
else{
tree[root << 1] = (label[root].mul * tree[root << 1] + label[root].add * (len - (len >> 1))) % p;/***长度划分***/
tree[root << 1 | 1] = (label[root].mul * tree[root << 1 | 1] + label[root].add * (len >> 1)) % p;
label[root << 1].add = (label[root].mul * label[root << 1].add + label[root].add) % p;
label[root << 1 | 1].add = (label[root].mul * label[root << 1 | 1].add + label[root].add) % p;
label[root << 1].mul = (label[root << 1].mul * label[root].mul) % p;
label[root << 1 | 1].mul = (label[root << 1 | 1].mul * label[root].mul) % p;
label[root].add = 0; label[root].mul = 1;
}
}
void build(int l, int r, int root)
{
label[root].add = 0; label[root].mul = 1;
if(l == r){
scanf("%lld", &tree[root]); return;
}
int mid = (l + r) >> 1;
build(lson); build(rson);
pushUp(root);
}
void update(int l, int r, int root, int L, int R, int tag, int c)
{
if(L == l && R == r){
if(tag == 1){
tree[root] = tree[root] * c % p;
label[root].add = label[root].add * c % p;
label[root].mul = label[root].mul * c % p;
}else{
tree[root] = (tree[root] + c * (r - l + 1)) % p;
label[root].add = (label[root].add + c) % p;
}
return;
}
pushDown(root, r - l + 1);
int mid = (l + r) >> 1;
if(L >= mid + 1) update(rson, L, R, tag, c);
else if(R <= mid) update(lson, L, R, tag, c);
else{
update(lson, L, mid, tag, c); update(rson, mid + 1, R, tag, c);
}
pushUp(root);
}
long long query(int l, int r, int root, int L, int R)
{
if(L == l && R == r){
return tree[root] % p;
}
pushDown(root, r - l + 1);
int mid = (l + r) >> 1;
if(L >= mid + 1) return (query(rson, L, R) % p);
else if(R <= mid) return (query(lson, L, R) % p);
else{
return ((query(lson, L, mid) + query(rson, mid + 1, R)) % p);
}
}
int main()
{
scanf("%d%d", &n, &p);
build(1, n, 1);
scanf("%d", &q);
for(int cas = 1; cas <= q; cas++){
int tag, t, g, c;
scanf("%d", &tag);
if(tag == 1){
scanf("%d%d%d", &t, &g, &c);
update(1, n, 1, t, g, 1, c);
}
else if(tag == 2){
scanf("%d%d%d", &t, &g, &c);
update(1, n, 1, t, g, 2, c);
}
else{
scanf("%d%d", &t, &g);
printf("%lld\n", query(1, n, 1, t, g) % p);
}
}
return 0;
}

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

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

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

  4. 【题解】洛谷P2023 [AHOI2009] 维护序列(线段树)

    洛谷P2023:https://www.luogu.org/problemnew/show/P2023 思路 需要2个Lazy-Tag 一个表示加的 一个表示乘的 需要先计算乘法 再计算加法 来自你谷 ...

  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. POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)

    POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...

  9. POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询)

    POJ.3468 A Simple Problem with Integers(线段树 区间更新 区间查询) 题意分析 注意一下懒惰标记,数据部分和更新时的数字都要是long long ,别的没什么大 ...

随机推荐

  1. [WPF]鼠标位置捕捉

    private void StackPanel_MouseMove(object sender, MouseEventArgs e) {     Debug.WriteLine("Move& ...

  2. decode与case when 函数

    百度百科: DECODE函数,是ORACLE公司的SQL软件ORACLE PL/SQL所提供的特有函数计算方式,以其简洁的运算方式,可控的数据模型和灵活的格式转换而闻名. DECODE 中的if-th ...

  3. git 版本回退方法

    ORIG_HEAD 某些操作,例如 merage / reset 会把 merge 之前的 HEAD 保存到 ORIG_HEAD 中,以便在 merge 之后可以使用 ORIG_HEAD 来回滚到合并 ...

  4. Flask开发系列之快速入门

    Flask开发系列之快速入门 文档 一个最小的应用 调试模式 路由 变量规则 构造 URL HTTP 方法 静态文件 模板渲染 访问请求数据 环境局部变量 请求对象 文件上传 Cookies 重定向和 ...

  5. laravel 学习之第一章

    LTS : long time support. download url : http://www.golaravel.com/download/ 第一篇 目录介绍: ​ resource:包含了原 ...

  6. RBAC | YAML |

    YAML配置文件: 1.凡是可以在application.properties配置的文件,都可以在application.yaml文件中配置 2.properties的优先级大于yaml的优先级 后端 ...

  7. win10将mongodb加入系统服务,官方源码报错问题记录

    进入C:\Program Files\MongoDB\Server\3.6目录下 1.编写配置文件mongodb.cfg: dbpath=D:\MongoDB\data\db #数据库路径 logpa ...

  8. Ubuntu伪破解Navicat12方法

    一.去官网下载navicat112_premium_cs_x64 for linux版本二.用tar解压安装包三.navicat解压即可用,直接进入解压后的目录,然后用‘./’运行start_navi ...

  9. 【学习】024 springCloud

    单点系统架构 传统项目架构 传统项目分为三层架构,将业务逻辑层.数据库访问层.控制层放入在一个项目中. 优点:适合于个人或者小团队开发,不适合大团队开发. 分布式项目架构 根据业务需求进行拆分成N个子 ...

  10. MYSQL利用merge存储引擎来实现分表

      创建user1和user2两个分表 建表语句如下:只是表名不一样,其他字段信息及主键一致. CREATE TABLE IF NOT EXISTS user1( id INT(11) NOT NUL ...