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 又乘又加的线段树的更多相关文章

  1. Luogu 45887 全村最好的嘤嘤刀(线段树 树状数组)

    https://www.luogu.org/problemnew/show/T45887 题目背景 重阳节到了,我们最好的八重樱拥有全村最好的嘤嘤刀…… 题目描述 在绯玉丸力量的影响下,八重村成了一条 ...

  2. luogu P5142 区间方差 十分优美的线段树

    又来了个维护方差的线段树.... 大致推导过程(字丑多包涵QAQ) 注意取模时要加一些100000007防止出现负数.. #include<cstdio> #include<iost ...

  3. luogu P3834 【模板】可持久化线段树 1(主席树) 查询区间 [l, r] 内的第 k 小/大值

    ————————————————版权声明:本文为CSDN博主「ModestCoder_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明.原文链接:https:// ...

  4. luogu P1712 [NOI2016]区间 贪心 尺取法 线段树 二分

    LINK:区间 没想到尺取法. 先说暴力 可以发现答案一定可以转换到端点处 所以在每个端点从小到大扫描线段就能得到答案 复杂度\(n\cdot m\) 再说我的做法 想到了二分 可以进行二分答案 从左 ...

  5. luogu P4632 [APIO2018] New Home 新家 线段树 set 二分

    写了一种比较容易理解 但是常数很大的sol. 容易发现可以扫描线. 维护好序列之后发现很难查距离 考虑二分. 这里二分可以在线段树上进行 当然可能存在一些问题 如果离散化的话需要处理一些比较麻烦的细节 ...

  6. 【LUOGU???】WD与地图 整体二分 线段树合并

    题目大意 有一个简单有向图.每个点有点权. 有三种操作: 修改点权 删除一条边 询问和某个点在同一个强连通分量中的点的前 \(k\) 大点权和. \(n\leq 100000,m,q\leq 2000 ...

  7. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  8. Luogu 4556 雨天的尾巴 - 启发式合并线段树

    Solution 用$col$记录 数量最多的种类, $sum$记录 种类$col$ 的数量. 然后问题就是树上链修改, 求 每个节点 数量最多的种类. 用树上差分 + 线段树合并更新即可. Code ...

  9. hdu 5111 树链剖分加函数式线段树

    这题说的是给了两棵树,各有100000 个节点,然后Q个操作Q<=50000; 每个操作L1 R1 L2 R2.因为对于每棵树都有一个与本棵树其他点与众不同的值, 最后问 在树上从L1到R1这条 ...

随机推荐

  1. == 和 equals 的区别是什么?

    已经有很多人说过二者的区别了,我直接上代码. String strA = "123"; String strB = "123"; String strC = & ...

  2. Maven ResourceBundle.getBundle读取Properties异常MissingResourceException: Can't find bundlei解决方法

    参考:https://blog.csdn.net/thousa_ho/article/details/72817616 问题描述 ResourceBundle读取properties配置文件提示 Mi ...

  3. 一种利用ADO连接池操作MySQL的解决方案(VC++)

    VC++连接MySQL数据库 常用的方式有三种:ADO.mysql++,mysql API ; 本文只讲述ADO的连接方式. 为什么要使用连接池? 对于简单的数据库应用,完全可以先创建一个常连接(此连 ...

  4. Nginx内置的嵌入变量

    Nginx核心模块ngx_http_core_module自带有许多内置嵌入的变量,这些变量方便我们配置和使用nginx,在nginx的配置文件中我们可以以$开头直接使用这些变量,这些变量表示客户端请 ...

  5. Python处理PDF和Word文档常用的方法

    Python处理PDF和Word文档的模块是PyPDF2,使用之前需要先导入. 打开一个PDF文档的操作顺序是:用open()函数打开文件并用一个变量来接收,然后把变量给传递给PdfFileReade ...

  6. python基础知识-12-模块的了解

    python其他知识目录 1.模块介绍: Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句.模块让你能够有逻辑地组织你 ...

  7. Kubernetes探索学习002--Kubernetes的基本使用

    Kubernetes 的基本使用方法 原则:使用YAML文件描述你要部署的API对象! 以部署nginx静态站点为例,具体操作及内容如下 1.编写YAML文件 [root@kubernetes01 ~ ...

  8. "prefs:root" or "App-Prefs:root"

    iOS 苹果审核也是看心情的吗?已经上线几个版本了,新版本提交审核居然被查出来了! Guideline 2.5.1 - Performance - Software Requirements Your ...

  9. Vue的computed计算属性是如何实现的

    一个开始 有如下代码,full是一个计算属性,开始,他的值是'hello world',1s后,msg变成了‘I like’, full的值同步变成了'I like world';其原理解析来看一下. ...

  10. 【探路者】final贡献分配

     [探路者]组成员及各位博客地址. 1蔺依铭:http://www.cnblogs.com/linym762/ 2张恩聚:http://www.cnblogs.com/zej87/ 3米赫:http: ...