当前位置:网站首页>Luogu P3373: 线段树
Luogu P3373: 线段树
2022-08-01 00:28:00 【JackDawn!?】
题目
点我去找题目
大意就是有若干数组成的一个序列,有三种操作,一种是让一个区间内每个数字加上一个数;一种是让一个区间内每个数字都乘上一个数字;最后一种是查询。
思路
这其实是一道模版题,只不过相比最基础的线段树来说多了一种标记,那我们要解决的主要问题就是如何来维护这两种标记。
维护时的主要问题有以下两个:
- 打标记的时候如何打
- 标记下放的时候如何下放
矛盾的地方实际上就是,我在添加一种标记的时候,需不需要处理另一种标记;如果需要,该怎么处理才能使这棵树的正确性不变。
我们可以通过人为设定优先级的方式来解决:
对于一个节点k, f[k]代表区间和, madd[k]代表加法标记, mmul[k]代表乘法标记
- 先考虑加法优先
则对于节点k的子节点来说, 规定在更新子节点的时候,先处理父节点传下来的加法标记,再处理父节点传下来的乘法标记,即先加后乘。那么我们在给一个区间加上数字z的时候,由小学学过的四则运算的性质,我们可以得到madd[k] += z/mmul[k]。明显这样处理之后按照规定的优先级就可以正确更新子节点的值了。 - 考虑乘法优先
对于节点k的子节点来说, 规定在更新子节点的时候,先处理父节点传下来的乘法标记,再处理父节点传下来的加法标记,即先乘后加。那么我们在给一个区间乘上数字z的时候,按照乘法分配律可以得到madd[k] *= z。
对于上面的两种做法,第一种做法由于存在整数的除法,故可能存在精度的问题;第二种做法虽然可能造成溢出,但是题目里说明了答案需要取模,所以溢出的问题也解决了,那我们就选择第二种做法。
代码
#include <cstdio>
using namespace std;
#define lc k<<1
#define rc k<<1|1
typedef long long ll;
const int maxn = 1e5+5;
ll a[maxn], f[4*maxn], madd[4*maxn], mmul[4*maxn];
int n, m, p;
inline void buildTree(int k, int l, int r) {
// k l r 分别是当前处理节点的下标 当前区间的左端点 当前区间的右端点 下同
madd[k] = 0; mmul[k] = 1;
if(l == r) {
f[k] = a[l]; return; }
int m = (l+r) >> 1;
buildTree(lc, l, m);
buildTree(rc, m+1, r);
f[k] = (f[lc] + f[rc])%p;
}
inline void pushdown(int k, int l, int r) {
int m = (l+r) >> 1;
f[lc] = (f[lc]*mmul[k] + madd[k]*(m-l+1))%p;
f[rc] = (f[rc]*mmul[k] + madd[k]*(r-m))%p;
mmul[lc] = (mmul[lc]*mmul[k]) % p;
mmul[rc] = (mmul[rc]*mmul[k]) % p;
madd[lc] = (madd[lc]*mmul[k] + madd[k]) % p;
madd[rc] = (madd[rc]*mmul[k] + madd[k]) % p;
mmul[k] = 1;
madd[k] = 0;
}
inline void add(int k, int l, int r, int x, int y, ll z) {
if(l == x && r == y) {
madd[k] = (madd[k] + z) % p;
f[k] = (f[k] + z*(r-l+1)) % p;
return;
}
pushdown(k, l, r);
int m = (l+r) >> 1;
if(y <= m) {
add(lc, l, m, x, y, z);
} else if(x > m) {
add(rc, m+1, r, x, y, z);
} else {
add(lc, l, m, x, m, z);
add(rc, m+1, r, m+1, y, z);
}
f[k] = (f[lc] + f[rc]) % p;
}
inline void mul(int k, int l, int r, int x, int y, ll z) {
if(l == x && r == y) {
madd[k] = (madd[k]*z) % p;
mmul[k] = (mmul[k]*z) % p;
f[k] = (f[k] * z) % p;
return;
}
pushdown(k, l, r);
int m = (l+r) >> 1;
if(y <= m) {
mul(lc, l, m, x, y, z);
} else if(x > m) {
mul(rc, m+1, r, x, y, z);
} else {
mul(lc, l, m, x, m, z);
mul(rc, m+1, r, m+1, y, z);
}
f[k] = (f[lc] + f[rc]) % p;
}
inline ll query(int k, int l, int r, int x, int y) {
if(l == x && r == y) {
return f[k];
}
pushdown(k, l, r);
int m = (l+r) >> 1;
if(y <= m) {
return query(lc, l, m, x, y);
} else if(x > m) {
return query(rc, m+1, r, x, y);
} else {
return query(lc, l, m, x, m) + query(rc, m+1, r, m+1, y);
}
}
int main(void)
{
// freopen("in.txt", "r", stdin);
scanf("%d%d%d", &n, &m, &p);
for(int i = 1; i <= n; ++i) {
scanf("%lld", &a[i]);
}
buildTree(1, 1, n);
int x, y, op;
ll k;
while(m--) {
scanf("%d", &op);
if(op == 1) {
scanf("%d%d%lld", &x, &y, &k);
mul(1, 1, n, x, y, k);
} else if(op == 2) {
scanf("%d%d%lld", &x, &y, &k);
add(1, 1, n, x, y, k);
} else {
scanf("%d%d", &x, &y);
printf("%lld\n", query(1, 1, n, x, y)%p);
}
}
return 0;
}
边栏推荐
- 精心总结十三条建议,帮你创建更合适的MySQL索引
- 继承的注意事项
- 类和对象:中
- SVN server construction + SVN client + TeamCity integrated environment construction + VS2019 development
- Flutter教程之四年开发经验的高手给的建议
- Interview Question: Implementing Deadlocks
- Redis五种数据类型简介
- lua入门案例实战123DIY
- Recommendation system: Summary of common evaluation indicators [accuracy rate, precision rate, recall rate, hit rate, (normalized depreciation cumulative gain) NDCG, mean reciprocal ranking (MRR), ROC
- JS时间戳的意义是什么?知道sql会考虑加时间戳,JS的时间戳用于什么场景?
猜你喜欢

MYSQL-批量插入数据

Flink 1.13(八)CDC

Google Earth Engine——Error: Image.clipToBoundsAndScale, argument ‘input‘: Invalid type的错误解决

精心总结十三条建议,帮你创建更合适的MySQL索引

《ArchSummit:时代的呐喊,技术人听得到》

南方科技大学:Xiaoying Tang | AADG:视网膜图像分割领域泛化的自动增强
![[Microservice] Distributed Transaction Solution - Seata](/img/a8/fc6c24e4d42dfb635bad786cc02164.png)
[Microservice] Distributed Transaction Solution - Seata

/etc/sysconfig/network-scripts configure the network card

推荐系统:常用评价指标总结【准确率、精确率、召回率、命中率、(归一化折损累计增益)NDCG、平均倒数排名(MRR)、ROC曲线、AUC(ROC曲线下的面积)、P-R曲线、A/B测试】

Redis五种数据类型简介
随机推荐
编译型语言和解释型语言的区别
TFC CTF 2022 WEB Diamand WriteUp
推荐系统:常用评价指标总结【准确率、精确率、召回率、命中率、(归一化折损累计增益)NDCG、平均倒数排名(MRR)、ROC曲线、AUC(ROC曲线下的面积)、P-R曲线、A/B测试】
Mysql environment installation under Linux (centos)
[1161. The maximum sum of elements in the layer]
逐步手撕轮播图3(保姆级教程)
博弈论(Depu)与孙子兵法(42/100)
精心总结十三条建议,帮你创建更合适的MySQL索引
Design the message queue storage MySQL form of message data
Keil nRF52832下载失败
vim的基本使用-命令模式
[AMEX] LGBM Optuna美国运通信用卡欺诈赛 kaggle
/etc/sysconfig/network-scripts 配置网卡
Named Entity Recognition - Model: BERT-MRC
Likou Binary Tree
Inheritance and friend, static member relationship
One line of code to solve CoreData managed object properties change in SwiftUI problem of animation effects
2022年最新重庆建筑八大员(电气施工员)模拟题库及答案
Classes and Objects: Medium
cmake入门学习笔记