Luogu 3373 又乘又加的线段树
Luogu 3373 又乘又加的线段树
当给一个节点加上一个加法标记时,直接把加法标记 += 新值;
当给一个节点加上一个乘法标记时,把乘法标记和加法标记同时 *= 新值。(注意pushdown函数中也要这样!)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define space putchar(' ')
#define enter putchar('\n')
template <class T>
bool read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
else if(c == EOF) return 0;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
return 1;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 100005;
int n, m, P;
ll a[N], data[4*N], mul[4*N], add[4*N];
void calc(ll &x, ll y, ll z){ // x = x * y + z
x = (x * y % P + z % P) % P;
}
void build(int k, int l, int r){
mul[k] = 1;
if(l == r) return (void)(data[k] = a[l]);
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
data[k] = (data[k << 1] + data[k << 1 | 1]) % P;
}
void pushdown(int k, int l, int r){
if(mul[k] == 1 && add[k] == 0) return;
int mid = (l + r) >> 1;
calc(data[k << 1], mul[k], add[k] * (mid - l + 1));
calc(data[k << 1 | 1], mul[k], add[k] * (r - mid));
calc(mul[k << 1], mul[k], 0);
calc(mul[k << 1 | 1], mul[k], 0);
calc(add[k << 1], mul[k], add[k]);
calc(add[k << 1 | 1], mul[k], add[k]);
mul[k] = 1, add[k] = 0;
}
void change(int k, int l, int r, int ql, int qr, ll x, bool is_mul){
if(ql <= l && qr >= r){
if(is_mul){
data[k] = data[k] * x % P;
mul[k] = mul[k] * x % P;
add[k] = add[k] * x % P;
}
else{
data[k] = (data[k] + x * (r - l + 1) % P) % P;
add[k] = (add[k] + x) % P;
}
return;
}
pushdown(k, l, r);
int mid = (l + r) >> 1;
if(ql <= mid) change(k << 1, l, mid, ql, qr, x, is_mul);
if(qr > mid) change(k << 1 | 1, mid + 1, r, ql, qr, x, is_mul);
data[k] = (data[k << 1] + data[k << 1 | 1]) % P;
}
ll query(int k, int l, int r, int ql, int qr){
if(ql <= l && qr >= r) return data[k];
pushdown(k, l, r);
int mid = (l + r) >> 1;
ll ret = 0;
if(ql <= mid) ret = (ret + query(k << 1, l, mid, ql, qr)) % P;
if(qr > mid) ret = (ret + query(k << 1 | 1, mid + 1, r, ql, qr)) % P;
return ret;
}
int main(){
read(n), read(m), read(P);
for(int i = 1; i <= n; i++)
read(a[i]), a[i] %= P;
build(1, 1, n);
while(m--){
int op, l, r;
read(op), read(l), read(r);
if(op < 3){
ll x;
read(x);
if(op == 2) change(1, 1, n, l, r, x, 0);
else change(1, 1, n, l, r, x, 1);
}
else write(query(1, 1, n, l, r)), enter;
}
return 0;
}
Luogu 3373 又乘又加的线段树的更多相关文章
- Luogu 45887 全村最好的嘤嘤刀(线段树 树状数组)
https://www.luogu.org/problemnew/show/T45887 题目背景 重阳节到了,我们最好的八重樱拥有全村最好的嘤嘤刀…… 题目描述 在绯玉丸力量的影响下,八重村成了一条 ...
- luogu P5142 区间方差 十分优美的线段树
又来了个维护方差的线段树.... 大致推导过程(字丑多包涵QAQ) 注意取模时要加一些100000007防止出现负数.. #include<cstdio> #include<iost ...
- luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值
————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...
- luogu P1712 [NOI2016]区间 贪心 尺取法 线段树 二分
LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左 ...
- luogu P4632 [APIO2018] New Home 新家 线段树 set 二分
写了一种比较容易理解 但是常数很大的sol. 容易发现可以扫描线. 维护好序列之后发现很难查距离 考虑二分. 这里二分可以在线段树上进行 当然可能存在一些问题 如果离散化的话需要处理一些比较麻烦的细节 ...
- 【LUOGU???】WD与地图 整体二分 线段树合并
题目大意 有一个简单有向图.每个点有点权. 有三种操作: 修改点权 删除一条边 询问和某个点在同一个强连通分量中的点的前 \(k\) 大点权和. \(n\leq 100000,m,q\leq 2000 ...
- bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...
- Luogu 4556 雨天的尾巴 - 启发式合并线段树
Solution 用$col$记录 数量最多的种类, $sum$记录 种类$col$ 的数量. 然后问题就是树上链修改, 求 每个节点 数量最多的种类. 用树上差分 + 线段树合并更新即可. Code ...
- hdu 5111 树链剖分加函数式线段树
这题说的是给了两棵树,各有100000 个节点,然后Q个操作Q<=50000; 每个操作L1 R1 L2 R2.因为对于每棵树都有一个与本棵树其他点与众不同的值, 最后问 在树上从L1到R1这条 ...
随机推荐
- windows 平台安装 ffmpeg
一.从https://ffmpeg.zeranoe.com/builds/中下载ffmpeg的static版本: 二.将下载下来的“ffmpeg-4.0.2-win64-static.zip”解压到任 ...
- Netty源码分析第7章(编码器和写数据)---->第2节: MessageToByteEncoder
Netty源码分析第七章: Netty源码分析 第二节: MessageToByteEncoder 同解码器一样, 编码器中也有一个抽象类叫MessageToByteEncoder, 其中定义了编码器 ...
- HDFS文件系统基础
HDFS架构实现 Hadoop当前稳定版本是Apache Hadoop 2.9.2,最新版本是Apache Hadoop 3.1.1. http://hadoop.apache.org/docs/ H ...
- 如何快速搭建yum源
yum命令能够从指定的服务器自动下载rpm包并安装,它最强大的地方就是可以自动处理软件包的依赖关系,能够一次安装所有依赖的关系包.下面将通过虚拟机平台介绍两种快速搭建yum源的方法: 一.有网络的情况 ...
- Azure web site和web job的config文件加密方式
1.分析 由于Azure Web AppService平台的特殊性,所以在C#中原先的config加密方法DataProtectionConfigurationProvider和RSAProtecte ...
- lsmod命令详解
基础命令学习目录首页 原文链接:http://blog.sina.com.cn/s/blog_e6b2465d0101fuev.html lsmod——显示已载入系统的模块 lsmod 其实就是lis ...
- 教你用Python解决非平衡数据问题(附代码)
本文为你分享数据挖掘中常见的非平衡数据的处理,内容涉及到非平衡数据的解决方案和原理,以及如何使用Python这个强大的工具实现平衡的转换. 后台回复“不平衡”获取数据及代码~ 前言 好久没有更新自己写 ...
- JAVA分代收集机制详解
Java堆中是JVM管理的最大一块内存空间.主要存放对象实例. 在JAVA中堆被分为两块区域:新生代(young).老年代(old). 堆大小=新生代+老年代:(新生代占堆空间的1/3.老年代占堆空间 ...
- jenkins设置定时任务
每次都手动的构建项目显然不够方便,有时候需要定时地执行自动化测试脚本.例如,每天晚上定时执行 pjenkins.py 文件来运行自动化测试项目. 设置定时任务 前面已经创建的 “python test ...
- ajax 异步刷新
第一种方法,ajax实现:当然,ajax使用起来确实很简单就可以实现,但是里面的很多知识还是比较有点深的.我之前做页面时间自动刷新的功能就是用的ajax.完整代码是:1.getTime.php: 复制 ...